简体   繁体   English

后续行动:在Django Modelform中缺少必需的Charfield被保存为空字符串,并且不会引发错误

[英]Followup : missing required Charfield in django Modelform is saved as empty string and do not raise an error

If I try to save incomplete model instance in Django 1.10, I would expect Django to raise an error. 如果我尝试在Django 1.10中保存不完整的模型实例,那么我会期望Django引发错误。 It does not seem to be the case. 似乎并非如此。

models.py: models.py:

from django.db import models

class Essai(models.Model):
    ch1 = models.CharField(max_length=100, blank=False)
    ch2 = models.CharField(max_length=100, blank=False)

So I have two fields not allowed to be empty (default behavior, NOT NULL restriction is applied by Django at MySQL table creation). 因此,我有两个字段不允许为空(默认行为,Django在MySQL表创建时应用了NOT NULL限制)。 I expect Django to rase an error if one of the fields is not set before storing. 我希望Django在存储前未设置任何字段的情况下引发错误。

However, when I create an incomplete instance, the data is stored just fine: 但是,当我创建一个不完整的实例时,数据存储就很好了:

>>> from test.models import Essai
>>> bouh = Essai()
>>> bouh.ch1 = "some content for ch1"
>>> bouh.save()
>>> bouh.id
9
>>> bouh.ch1
'some content for ch1'
>>> bouh.ch2
''
>>> 

I would have expected Django to raise an error. 我本来希望Django引发错误。 If I force ch2 to None , however, it raises an error: 如果我将ch2强制为None ,则会引发错误:

>>> bouh = Essai()
>>> bouh.ch1 = "some content for ch1"
>>> bouh.ch2 = None
>>> bouh.save()
Traceback (most recent call last):
  (...)
    return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: NOT NULL constraint failed: test_essai.ch2
>>> bouh.id
>>> bouh.ch1
'some content for ch1'
>>> bouh.ch2
>>>

Explanation: Django is not raising an error as default behavior in this simple case because in SQL empty string "" is not equivalent to NULL, as stated in Django model blank=False does not work? 说明:在这种简单情况下,Django不会引发错误作为默认行为,因为在SQL中,空字符串""不等于NULL,如Django模型中所述, blank = False不起作用?

Now, if we look at ModelForm behavior, there seem to be a inconsistency in django doc: 现在,如果我们看一下ModelForm的行为,django doc中似乎有一个不一致之处:

According to: https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/#selecting-the-fields-to-use 根据: https : //docs.djangoproject.com/en/1.10/topics/forms/modelforms/#selecting-the-fields-to-use

Django will prevent any attempt to save an incomplete model, so if the model does not allow the missing fields to be empty, and does not provide a default value for the missing fields, any attempt to save() a ModelForm with missing fields will fail. Django会阻止保存不完整模型的任何尝试,因此,如果模型不允许丢失的字段为空,并且不为丢失的字段提供默认值,则任何尝试保存()带有丢失字段的ModelForm的尝试都会失败。 To avoid this failure, you must instantiate your model with initial values for the missing, but required fields:(…) 为了避免这种失败,您必须使用缺少值但必填字段的初始值实例化模型:(…)

a modelForm should not be saved with a missing field if there is no default value. 如果没有默认值,则不应将modelForm保存为缺少字段。

So with this ModelForm: class EssaiModelForm(forms.ModelForm): class Meta: model = Essai fields = ['ch1'] A form with only one field ch1 is generated. 因此,使用此ModelForm: class EssaiModelForm(forms.ModelForm): class Meta: model = Essai fields = ['ch1']生成仅包含一个字段ch1表单。

  • If ch1 is left empty, the validation fails at EssaiModelFormInstance.is_valid() as expected. 如果ch1保留为空,则验证EssaiModelFormInstance.is_valid()预期在EssaiModelFormInstance.is_valid()处失败。
  • If ch1 contains a value, the validation succeeds even though ch2 is still missing. 如果ch1包含一个值,则即使ch2仍然丢失,验证也会成功。 Then the EssaiModelFormInstance.save() succeeds, contrary to what is claimed in django documentation. 然后,与Django文档中要求的相反,EssaiModelFormInstance.save()成功。 ch2 is empty string and thus is compatible with SQL requirements ( NOT NULL ). ch2是空字符串,因此与SQL要求兼容( NOT NULL )。

So it seems that there is a default default value empty string "" for Charfield that is not accepted in form validation but that is accepted in save() validation. 因此,似乎Charfield有一个默认的默认值空字符串"" ,在表单验证中不接受 ,但在save()验证中可接受 This may require clarification in the documentation. 这可能需要在文档中进行说明。

As the two fields ch1 and ch2 are always required in your case, all you need to do is modify your model such that 由于在您的情况下始终需要两个字段ch1ch2 ,因此您所需要做的就是修改模型,以便

from django.db import models

class Essai(models.Model):
    ch1 = models.CharField(max_length=100)
    ch2 = models.CharField(max_length=100)

and include the fields in the form as 并以以下形式包含字段:

class EssaiModelForm(forms.ModelForm):
class Meta:
    model = Essai
    fields = ['ch1', 'ch2']

Django will automatically raise a validation error for this fields on is_valid() Django会在is_valid()上针对此字段自动引发验证错误

Or if you want to disallow empty string inputs to these fields blank=False will not work 或者,如果您要禁止向这些字段输入空字符串,则blank=False将不起作用

Refer this Django - how to set blank = False, required = False 参考此Django-如何设置blank = False,必填= False

There is a slightly notable difference in model and it's forms. 模型及其形式略有显着差异。 Model.save() performs no validation. Model.save()不执行任何验证。 So if it fails then probably it raises a database level IntegrityError. 因此,如果失败,则可能会引发数据库级别的IntegrityError。 For reducing risks of failure at database layer one need to call Model.full_clean() which is also done by ModelForm as documented here in django's validating objects . 为了降低数据库层发生故障的风险,需要调用Model.full_clean(),这也由ModelForm完成,如django的验证对象中所述

In my opinion, I expect from django that ModelForms are meant to validate and save data entered by client. 我认为,django希望ModelForms用于验证和保存客户输入的数据。 Model instantiated programmatically should follow the same control before saving into database. 以编程方式实例化的模型在保存到数据库之前应遵循相同的控制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM