【问题标题】:object created even if field was required即使需要字段,也会创建对象
【发布时间】:2018-07-03 07:31:45
【问题描述】:
#models.py

class Mymodel(models.Model):
    name = models.CharField(max_length=100,null=False,blank=False)
    email = models.EmailField(max_length=100,null=False,blank=False)
    password = models.CharField(max_length=120,null=False,blank=False)
    email_notification = models.BooleanField()




#views.py

obj=MyModel.objects.create(name="ok",password="dsfdsfdsfdsfsfds",email_notification=1)

即使电子邮件是必填字段,当我在管理面板中看到时,也会创建对象。可能是什么问题,为什么要创建对象,即使电子邮件字段是强制性的? 此外,如果我进入管理面板并打开该对象并单击保存,那么它会引发该电子邮件是必需的

【问题讨论】:

  • django 版本??
  • django 版本为 2.0.4
  • email = models.EmailField(max_length=100,null=False,blank=False) 不需要。
  • @marin 如果这不是必需的,为什么在 django 管理面板中单击保存时会显示错误。此外,如果需要 email = models.EmailField(max_length=100),则会出现同样的情况跨度>
  • 请上传完整的错误信息。

标签: python django django-models


【解决方案1】:

注意:您不必在字段中提供 null=False,blank=False,因为这些是默认使用的值。(请参阅 Django Field __int__ 签名。)。 p>

def __init__(self, verbose_name=None, name=None, primary_key=False,
                 max_length=None, unique=False, blank=False, null=False,
                 db_index=False, rel=None, default=NOT_PROVIDED, editable=True,
                 serialize=True, unique_for_date=None, unique_for_month=None,
                 unique_for_year=None, choices=None, help_text='', db_column=None,
                 db_tablespace=None, auto_created=False, validators=(),
                 error_messages=None):

默认情况下,数据库中的所有字段都是使用NOT NULL 约束创建的。 如果您为特定字段设置 null=True,那么 django 会在您的数据库中的列上设置 NULL 它是 Python 的 None 关键字的数据库等效项。

null 参数示例

假设我的my_app 中有以下Mymodel,并将email 字段设置为null=True

class MyModel(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(max_length=100, null=True)
    password = models.CharField(max_length=120)
    email_notification = models.BooleanField()

在外壳中,

>> from my_app.models import MyModel

>> new = MyModel.objects.create(name="ok",
                                password="dsfdsfdsfdsfsfds",
                                email_notification=1)
>> new.email == None
>> True # As you can see Django sets db value 
        # as NULL and when we query the data it converts back to Python `None` object.

不带 null 参数的示例

假设我的my_app 中有以下Mymodel。(记住null 默认为False

class MyModel(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(max_length=100)
    password = models.CharField(max_length=120)
    email_notification = models.BooleanField()

在外壳中,

>> from my_app.models import MyModel
>> new_obj = MyModel.objects.create(name="test",
                                password="test",
                                email_notification=1)
>> new_obj.email == ''
>> True

即,Django CharFieldTextField 默认值作为空字符串('')存储在数据库中。换句话说,如果你创建一个对象而不提供 CharField(或 TextField)的值,Django 会调用 get_default 方法并返回 ''(仅在这种情况下)。该值将存储在数据库中。

以下是get_default方法的源码。

def get_default(self):
    """Return the default value for this field."""
    return self._get_default()

@cached_property
def _get_default(self):
    if self.has_default():
        if callable(self.default):
            return self.default
        return lambda: self.default

    if not self.empty_strings_allowed or self.null and not connection.features.interprets_empty_strings_as_nulls:
        return return_None
    return str  # return empty string

让我们回答你的问题:

为什么要创建对象,即使电子邮件字段是强制性的?

答案是EmailFieldCharField 的一个实例,因此在数据库中创建对象时将使用默认值''。这就是为什么你没有收到django.db.utils.IntegrityError

>> new_obj = Mymodel.objects.create(name='tes1t', password='test1', email_notification=1)
>>> new_obj.email
''

另外,如果我转到管理面板并打开该对象并单击保存然后 它会引发一个错误,表明需要电子邮件

记住blanknull 不同。 null 纯粹与数据库相关,而 blank 与验证相关。 所以当你直接在 Python 代码中创建一个对象,或者自己执行原始 SQL 时,你实际上是绕过了 Django 的所有输入验证。但是在 admin 中,Django 是通过模型表单来验证输入的。由于在您的情况下 blank 设置为 False(不允许空白),模型表单将引发 Email is required 错误。

这里是 blank 参数的相关 Django 文档。

字段.空白

如果为 True,则该字段允许为空。默认为假。笔记 这与 null 不同。 null 纯粹与数据库相关, 而空白与验证相关。如果一个字段有空白=真,形成 验证将允许输入空值。如果一个字段有 blank=False,该字段为必填项。

其他资源

【讨论】:

  • 我用比更高层次的概述更简单的方式解释了同样的事情:)。
【解决方案2】:

django 没有问题,您必须创建正确的 Django 模型表单验证,这样空字符串就不会被忽略,并且会为空白字段引发错误。

【讨论】:

  • 是的,我只是这样做了,但是为什么不能通过管理面板创建相同的对象,如果可以通过命令完成的话
  • 实际上,管理面板也是建立在 Django Forms 之上的,他们使用了一些表单验证来检查必填字段是否为空。您可以通过 m.save(commit=False) 执行相同的验证,这实际上不会保存对象,然后您可以检查该字段是否为空并相应地引发异常。
  • 那么这是否意味着没有表单验证它不会停止根据模型约束创建对象。验证是必要的吗?
  • 是的,这是必要的。我也像你一样被困在一个项目上,但后来我意识到我们必须自己验证并相应地抛出异常。
猜你喜欢
  • 2021-10-18
  • 2020-01-07
  • 2020-05-25
  • 2020-08-28
  • 2011-10-08
  • 1970-01-01
  • 2018-09-13
  • 1970-01-01
  • 2018-11-11
相关资源
最近更新 更多