后续:缺少必需的django模型中的Charfield保存为空字符串,不会引发错误

时间:2016-09-28 05:54:38

标签: python mysql django validation django-models

如果我尝试在Django 1.10中保存不完整的模型实例,我会期望Django引发错误。情况似乎并非如此。

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)

所以我有两个字段不允许为空(默认行为,Django在MySQL表创建时应用NOT NULL限制。我希望Django在存储之前没有设置其中一个字段时会出错。

但是,当我创建一个不完整的实例时,数据存储得很好:

>>> 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
''
>>> 

我原本以为Django会引发错误。但是,如果我强制ch2None,则会引发错误:

>>> 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
>>>

说明:在这个简单的情况下,Django没有引发错误作为默认行为,因为在SQL中,空字符串""不等于NULL,如Django model blank=False does not work?中所述

现在,如果我们看看ModelForm行为,django doc似乎存在不一致:

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

  

Django将阻止任何保存不完整模型的尝试,因此如果模型不允许缺少的字段为空,并且没有为缺少的字段提供默认值,则任何尝试保存()缺少ModelForm字段将失败。为了避免这种失败,您必须使用缺少但必需的字段的初始值来实例化您的模型:(...)

如果没有默认值,则不应使用缺少的字段保存modelForm。

所以使用这个ModelForm: class EssaiModelForm(forms.ModelForm): class Meta: model = Essai fields = ['ch1'] 生成仅包含一个字段ch1的表单。

  • 如果ch1为空,则验证将在EssaiModelFormInstance.is_valid()处按预期失败。
  • 如果ch1包含值,则即使ch2仍然缺失,验证也会成功。然后EssaiModelFormInstance.save()成功,与django文档中声称的相反。 ch2为空字符串,因此与SQL要求(NOT NULL)兼容。

所以似乎Charfield的默认默认值空字符串""在表单验证中不接受但在保存时已接受( )验证。这可能需要在文档中进行说明。

2 个答案:

答案 0 :(得分:0)

由于您的案例中始终需要ch1ch2两个字段,因此您需要做的就是修改模型

from django.db import models

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

并将表单中的字段包含为

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

Django会自动为is_valid()

上的这些字段引发验证错误

或者,如果您想禁止对这些字段使用空字符串输入blank=False将不起作用

请参阅此Django - how to set blank = False, required = False

答案 1 :(得分:0)

模型和形式之间存在细微差别。 Model.save()不执行验证。因此,如果它失败,那么它可能会引发数据库级别的IntegrityError。为了降低数据库层失败的风险,需要调用Model.full_clean(),这也是由ModelForm完成的,如django's validating objects中所述。

在我看来,我希望来自django的ModelForms旨在验证和保存客户输入的数据。以编程方式实例化的模型应该在保存到数据库之前遵循相同的控制。