python - Django - POST is_valid() false,没有错误,也没有写入数据库
问题描述
我有一个简单的 html 表单,我可以在其中添加一些数据并将其提交以添加到数据库中。
这是表格:
<!-- MAIN CONTENT-->
<div class="main-content">
<div class="section__content section__content--w1830">
<div class="container-fluid">
<h1>Artikel</h1>
<br>
<br>
<div class="card">
<div class="card-header">Artikel hinzufügen</div>
<div class="card-body">
<form action="" method="post">
{% csrf_token %}
<div class="form-group">
<div class="row form-group">
<div class="col-4">
<label for="type" class="control-label mb-1">Typ</label>
<select name="type" id="type" class="form-control"
value=" {{ forms.artikel_typ }} ">
<option value="0">Bitte auswählen</option>
<option value="1">Raum</option>
<option value="2">Artikel</option>
<option value="3">Gerät</option>
<option value="4">Marketing</option>
<option value="5">Labor</option>
</select>
</div>
<div class="col-8">
<label for="bezeichnung" class="control-label mb-1"> Bezeichnung</label>
<input id="bezeichnung" name="bezeichnung" type="text" class="form-control"
data-val="true"
data-val-required="Bitte tragen Sie eine Bezeichnung ein!"
aria-required="true" aria-invalid="false"
placeholder="Bitte tragen Sie eine Bezeichnung ein." value ="{{ forms.bezeichnung }}">
</div>
</div>
</div>
<div class="card-body card-block">
<div class="row form-group">
<div class="col-4">
<label for="menge" class="control-label mb-1">Menge</label>
<input id="menge" type="number"
class="form-control" data-val="ture"
data-val-required="Bitte tragen Sie die Menge ein!"
aria-required="true" aria-invalid="false"
placeholder="Bitte geben Sie die Menge an." value=" {{ forms.menge }} ">
</div>
<div class="col-4">
<label for="einheit" class="control-label mb-1">Einheit</label>
<select name="einheit" value="{{ forms.einheit }}" id="einheit"
class="form-control"
data-val-required="Bitte tragen Sie die Einheit ein!"
aria-required="true" aria-invalid="false">
<option value="0">Bitte auswählen</option>
<option value="Euro">Euro</option>
<option value="Prozent">Prozent</option>
<option value="Minuten">Minuten</option>
<option value="Stück">Stück</option>
<option value="pauschal">pauschal</option>
</select>
</div>
<div class="col-4">
<label for="preis">Preis</label>
<input id="preis" value="{{ forms.preis }}" step="0.01" type="number"
class="form-control"
data-val="ture"
data-val-required="Bitte tragen Sie den Preis ein!"
aria-required="true" aria-invalid="false"
placeholder="Bitte tragen Sie den Preis ein!">
</div>
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-primary btn-sm" value="post" action="articles">
<i class="fa fa-dot-circle-o"></i> Artikel hinzufügen
</button>
</div>
</div>
</form>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-lg-9">
<div class="table-responsive table--no-card m-b-30">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>id</th>
<th>artikel_typ</th>
<th>bezeichnung</th>
<th>menge</th>
<th>preis</th>
<th>einheit</th>
</tr>
</thead>
<tbody>
{% for d in data %}
<tr>
<td>{{ d.id }}</td>
{% if d.artikel_typ == 1 %}
<td> Raum</td>
{% endif %}
{% if d.artikel_typ == 2 %}
<td> Artikel</td>
{% endif %}
{% if d.artikel_typ == 3 %}
<td> Gerät</td>
{% endif %}
{% if d.artikel_typ == 4 %}
<td> Marketing</td>
{% endif %}
{% if d.artikel_typ == 5 %}
<td> Labor</td>
{% endif %}
<td>{{ d.bezeichnung }}</td>
<td>{{ d.menge }}</td>
<td>{{ d.preis }}</td>
<td>{{ d.einheit }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- END PAGE CONTAINER-->
这是使用的代码的 views.py 部分:
def articles(request):
data = Artikel.objects.all()
aform = ArtikelForm( data=request.POST or None)
if request.method == "POST":
if aform.is_valid():
artikel_type = aform.cleaned_data['artikel_typ']
bezeichnung = aform.cleaned_data['bezeichnung']
menge = aform.cleaned_data['menge']
preis = aform.cleaned_data['preis']
einheit = aform.cleaned_data['einheit']
artikel = Artikel(artikel_typ=artikel_type, bezeichnung=bezeichnung, menge=menge, preis=preis, einheit=einheit)
artikel.save()
return redirect("articles")
return render(request, "articles.html", {"data": data, "forms": aform})
这是我定义的forms.py:
from django import forms
类 ArtikelForm(forms.Form):
artikel_typ = forms.IntegerField()
bezeichnung = forms.CharField(max_length=100)
menge = forms.FloatField()
preis = forms.FloatField()
einheit = forms.CharField(max_length=100)
这是models.py中定义的模型:
class Artikel(models.Model):
id = models.AutoField(unique=True, primary_key=True)
artikel_typ = models.IntegerField(null=True)
bezeichnung = models.TextField()
menge = models.FloatField(blank=True, null=True)
preis = models.FloatField(blank=True, null=True)
einheit = models.TextField(blank=True, null=True)
所以我尝试了模型、表单和 python 控制台。我将数据添加到 dict,创建了 ArtikelForm 的实例并调用 is_valid(),它返回 true,clean_data 看起来不错。
但是,当提交表单时,is_valid() 返回下降,并且字段值返回 None 对于整数和浮点字段,检索 char 字段并显示我输入/选择的信息,HTTP 响应为 200 并被重定向。有没有人可以解决我如何解决这个问题?谢谢!
解决方案
您在这里遇到了一些问题,我将尝试详细解释它们。每当您在 Django 中创建表单时,您都必须为其创建一个类,该类定义所有字段以及如何“构建”表单,您已在forms.py
. 即使你正确地做到了,你可能想要考虑继承,forms.ModelForm
因为它会使表单创建更容易。基本上 aModelForm
会自动为您制作一个表格Model
。在这里查看
更多信息。
真正神奇的views.py
地方是您处理请求并以适当的形式返回呈现的 html 的地方。您所做的是在您的模型中查询某些对象data = Artikel.objects.all()
,然后创建表单aform = ArtikelForm( data=request.POST or None)
,然后检查该方法是否是POST
请求以验证表单并执行其他操作。但是,在底部,当您返回时,您不会将表单传递给 html。你需要确保你传递了一个包含所有内容的字典,例如return render(request, 'articles.html', {'data': data, 'forms': aform})
。这应该可以解决无法从模板访问表单的问题。但这意味着您将访问表单中的特定字段,如下所示:{{ forms.artikel_typ }}
.
另外我想指出,在您views.py
访问表单内的数据以保存到您通常想要获取“清理数据”的模型时。这是 Django 所做的,以确保所有字段都变成某种 python 标准,以便轻松使用它并将其保存到模型中。您访问它的方式是通过执行aform.cleaned_data['artikel_typ']
. 也可以考虑使用酥脆的表格,这样您就不必手动制作表格。
编辑
在您的 html 模板中,您需要做的就是访问{{ forms.field_name }}
,它将放入该字段小部件的 html。无需手动创建表单,这就是您使用 Django 表单的原因。见下文:
<!-- MAIN CONTENT-->
<div class="main-content">
<div class="section__content section__content--w1830">
<div class="container-fluid">
<h1>Artikel</h1>
<br>
<br>
<div class="card">
<div class="card-header">Artikel hinzufügen</div>
<div class="card-body">
<form action="" method="post">
{% csrf_token %}
{{ forms.artikel_typ }}
{{ forms.bezeichnung }}
{{ forms.menge }}
{{ forms.preis }}
{{ forms.einheit }}
</form>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-lg-9">
<div class="table-responsive table--no-card m-b-30">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>id</th>
<th>artikel_typ</th>
<th>bezeichnung</th>
<th>menge</th>
<th>preis</th>
<th>einheit</th>
</tr>
</thead>
<tbody>
{% for d in data %}
<tr>
<td>{{ d.id }}</td>
{% if d.artikel_typ == 1 %}
<td> Raum</td>
{% endif %}
{% if d.artikel_typ == 2 %}
<td> Artikel</td>
{% endif %}
{% if d.artikel_typ == 3 %}
<td> Gerät</td>
{% endif %}
{% if d.artikel_typ == 4 %}
<td> Marketing</td>
{% endif %}
{% if d.artikel_typ == 5 %}
<td> Labor</td>
{% endif %}
<td>{{ d.bezeichnung }}</td>
<td>{{ d.menge }}</td>
<td>{{ d.preis }}</td>
<td>{{ d.einheit }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- END PAGE CONTAINER-->
如果您想重新排列它们的去向并进行一些样式设置,这将单独访问每个字段,但您也可以简单地使用{{ forms }}
它将呈现所有字段。
推荐阅读
- html - 有什么方法可以在 scss 的帮助下更改主题
- javascript - 通过Javascript更改Flask模板中的图像
- ruby-on-rails - 在 yaml 文件中设置多个值,为什么只用 Rails 得到第一个?
- javascript - 基于输入值的表格计算器
- grafana - 如何超时 grafana 会话 cookie
- python - Python 3.6 - 具有列表理解迭代的多处理映射,包含在主上下文中定义的列表
- php - 如何测试处理 Eloquent 模型的 Laravel 包?
- arrays - 使用 while 和数组重复输入
- javascript - React:将函数参数应用于闭包打破了模块化
- oracle - ORA-01758: 表必须为空才能添加强制 (NOT NULL) 列