python - Django:ModelForm 未绑定(bind)到 request.POST

标签 python django django-forms modelform

我有以下模型:

class Tracking(models.Model):

    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    week = models.IntegerField(choices=settings.WEEK_CHOICES, blank=True)
    term = models.IntegerField(choices=settings.TERM_CHOICES, blank=True)
    year = models.IntegerField(choices=settings.YEAR_CHOICES, blank=True)
    target = models.CharField(max_length=256, blank=True)
    monday = models.IntegerField()
    tuesday = models.IntegerField()
    wednesday = models.IntegerField()
    thursday = models.IntegerField()
    friday = models.IntegerField()

链接到此表单:

class AddTrackingForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):   
        super(AddTrackingForm, self ).__init__(*args, **kwargs)

    class Meta:

        model = models.Tracking
        fields = '__all__'

用户填写表单后,我想将实例保存到数据库:

class TrackingView(generic.TemplateView):

    template_name = "tracking.html"
    def get(self, request, *args, **kwargs):

        form = forms.AddTrackingForm()
        form.fields['person'].queryset = models.Person.objects.filter(active=True).order_by('-last_name', '-first_name')
        return render(request, self.template_name, {'form': form, })

    def post(self, request, *args, **kwargs):
        form = forms.AddTrackingForm(request.POST)
        if form.is_valid():
            model_instance = form.save(commit=False)
            model_instance.person = models.Person.objects.get(id=int(request.POST['person']))

            model_instance.save()
        return redirect('/tracking')

但是,form.is_valid()永远不会返回 True。打印出错误使 form.errors 为空白和:<bound method BaseForm.non_field_errors of <AddTrackingForm bound=False, valid=False, fields=(person;week;term;year;b1;b2;monday;tuesday;wednesday;thursday;friday)>>对于 form.non_field_errors .

无论我如何尝试,我都无法绑定(bind)实例。我认为发布数据可能是作为字符串接收的,而不是 model.IntegerField() 的有效数据。的,所以我可能需要覆盖 form.clean()并将所有相关字段转换为整数。然而,这没有用。还有什么可能导致我的表单无法绑定(bind)到实例?

更新 这是我的模板。该表单位于表格中,我进行 Ajax 查询以确保在提交表单之前尚未输入数据:

<tbody>
    <tr>                        
    <form id="tracking_form" method="POST" action="/tracking">                      
        {% csrf_token %}
    {% for field in form %}
        <td>{{ field }}</td>
    {% endfor %}
    <td><input type="button" class="btn btn-default" onclick="submitIfUnique()" value="Add Points"></td>
    </form>
    </tr>
</tbody>
...
<script>
        var form_data = {
            'person': $('#id_person').val(),
            'year': $('#id_year').val(),
            'term': $('#id_term').val(),
            'week': $('#id_week').val(),
        };

        $.ajax({
            url: "/api/tracking/is_unique", 
            method: "GET",
            dataType: "json",
            data: form_data,
            success: function(response){
                var form = $('#tracking_form');
                var submit = true;
                if(!response['is_unique']){
                    confirm = confirm("This data has already been entered for " + response['person'] + ". Are you sure you want to overwrite this?");
                    if(!confirm){ submit = false; }
                }
                if(submit){ form.submit(); }
            }
        });

</script>

我知道表单提交正确,因为我可以打印 TrackingView.post() 中请求的所有数据。 。为了完整起见,以下是模板在浏览器中呈现后的表单:

<form id="tracking_form" method="POST" action="/tracking">                      
  <input type='hidden' name='csrfmiddlewaretoken' value='EZ...Uc' />
<td><select name="person" required id="id_person">
    <option value="18" selected>Test Person 1</option>
    <option value="19">Test Person 2</option>
</select></td>      
<td><select name="week" required id="id_week">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
</select></td>                  
<td><select name="term" required id="id_term">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
</select></td>      
<td><select name="year" required id="id_year">
     <option value="2017">2017</option>
     <option value="2018">2018</option>
</select></td>
<td><input type="text" name="target" required id="id_target" /></td>
<td><input type="number" name="monday" min="0" max="100" required id="id_monday" /></td>
<td><input type="number" name="tuesday"  min="0" max="100" required id="id_tuesday" /></td>
<td><input type="number" name="wednesday"  min="0" max="100" required id="id_wednesday" /></td>
<td><input type="number" name="thursday" min="0" max="100" required id="id_thursday" /></td>
<td><input type="number" name="friday" min="0" max="100" required id="id_friday" /></td>
<td><input type="button" class="btn btn-default" onclick="submitIfUnique()" value="Add Points"></td>

最佳答案

您误解了您得到的输出。表单绑定(bind)的,否则form.errors将不起作用。但是 non_field_errors 是一个方法,您需要调用: form.non_field_errors()

主要问题是您总是在发布后重定向,即使表单无效。仅当它有效时才应该这样做;否则,您应该重新显示具有无效表单的模板。另外,您应该在该模板中显示 {{ form.errors }}

另请注意,您使用了错误的 View 基类; CreateView 将执行代码执行的所有操作,包括在出错时重新显示表单。一般来说,如果您发现自己在基于类的 View 上重写了 getpost,那么您就做错了。

关于python - Django:ModelForm 未绑定(bind)到 request.POST,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48798781/

相关文章:

python - 从排序列表创建字典

python - 迭代字典

django - 如何使用另一个数据库(非默认数据库)中的 auth_user?

python - 根据用户选择模型表单中显示哪些字段

python - 在 Django 表单中保存默认值

python - 通过 FTP 下载 zip 文件并在 Python 中提取内存中的文件

python - 表删除后 SQLAlchemy 行为不正确

python - 从远程数据库获取并存储到本地 Django

python - 如何使用不同的 Python 运行时将 Django/WSGI 部署为 azure web 应用程序?

python - 奇怪的 Django AuthenticationForm 行为