Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django模型字段验证_Python_Django_Django Models - Fatal编程技术网

Python Django模型字段验证

Python Django模型字段验证,python,django,django-models,Python,Django,Django Models,django中模型字段的验证应该放在哪里 我可以列出至少两种可能的选择:在模型的重载.save()方法中,或者在models.Field子类的.to_python()方法中(显然,要使其起作用,您必须编写自定义字段) 可能的用例: 当绝对需要确保空字符串不会写入数据库时(blank=False关键字参数在这里不起作用,它仅用于表单验证) 当需要确保“choices”关键字参数在数据库级别得到尊重时,而不仅仅是在管理接口中(类似于模拟枚举数据类型) 模型中还有一个类级属性empty\u str

django中模型字段的验证应该放在哪里

我可以列出至少两种可能的选择:在模型的重载.save()方法中,或者在models.Field子类的.to_python()方法中(显然,要使其起作用,您必须编写自定义字段)

可能的用例:

  • 当绝对需要确保空字符串不会写入数据库时(blank=False关键字参数在这里不起作用,它仅用于表单验证)
  • 当需要确保“choices”关键字参数在数据库级别得到尊重时,而不仅仅是在管理接口中(类似于模拟枚举数据类型)
模型中还有一个类级属性
empty\u strings\u allowed
。字段基类定义和派生类很乐意覆盖它,但它似乎不会对数据库级产生任何影响,这意味着我仍然可以使用空字符串字段构造模型并将其保存到数据库中。我想避免(是的,这是必要的)

可能的实现是

在实地一级:

class CustomField(models.CharField):
    __metaclass__ = models.SubfieldBase
    def to_python(self, value):
        if not value:
            raise IntegrityError(_('Empty string not allowed'))
        return models.CharField.to_python(self, value)
在模型层面:

class MyModel(models.Model)
    FIELD1_CHOICES = ['foo', 'bar', 'baz']
    field1 = models.CharField(max_length=255, 
               choices=[(item,item) for item in FIELD1_CHOICES])

    def save(self, force_insert=False, force_update=False):
        if self.field1 not in MyModel.FIELD1_CHOICES:
            raise IntegrityError(_('Invalid value of field1'))
        # this can, of course, be made more generic
        models.Model.save(self, force_insert, force_update)

也许,我遗漏了一些东西,而这可以做得更简单(更干净)?

如果我“清楚地”理解您的意思-您必须重写函数get\u db\u prep\u save,而不是to\u python

这方面的根本问题是验证应该发生在模型上。这在django(开发人员邮件列表上的搜索表单模型感知验证)中已经讨论了很长时间。它会导致重复或在命中数据库之前逃避验证

虽然这不会影响主干,但Malcolm的解决方案可能是避免重复的最干净的解决方案。

Django从1.2版开始就有了一个系统

在评论中,sebpiq说:“好的,现在有一个地方可以进行模型验证……除了它只在使用ModelForm时运行!所以问题仍然存在,当需要确保在db级别上遵守验证时,您应该怎么做?在哪里调用full_clean?”

不可能通过Python级别的验证来确保db级别的验证得到尊重。最接近的方法可能是在重写的
save
方法中调用
full\u clean
。默认情况下不会这样做,因为这意味着调用save方法的每个人现在最好准备捕获并处理
ValidationError

但即使您这样做,仍有人可以使用
queryset.update()
批量更新模型实例,这将绕过此验证。Django无法实现一个相当高效的
queryset.update()
,它仍然可以对每个更新的对象执行Python级别的验证

真正保证db级完整性的唯一方法是通过db级约束;通过ORM进行的任何验证都要求应用程序代码的编写者知道何时实施验证(并处理验证失败)


这就是为什么默认情况下只在
ModelForm
中执行模型验证的原因-因为在ModelForm中已经有一种明显的方法来处理
ValidationError

我想您想要这个->

from django.db.models.signals import pre_save

def validate_model(sender, **kwargs):
    if 'raw' in kwargs and not kwargs['raw']:
        kwargs['instance'].full_clean()

pre_save.connect(validate_model, dispatch_uid='validate_models')

(抄袭自)

这实际上是个好主意。但是,我特别提到了.to_python(),因为它会在字段初始化后被激发(如果指定metaclass=models.SubfieldBase),因此验证会提前进行,这意味着如果传递字段的错误值,甚至无法初始化模型。也许,你的方式是正确的。至少对我来说有点道理。我已经在谷歌缓存中读到了它的内容。这是有道理的,是的。如果我不打算使用表单(不需要表单来输入数据,对吗?),这并没有多大帮助,但是这当然是避免重复我自己的一种方式。太好了,太好了,这太好了!我已经浏览了源代码(顺便问一下,有没有什么方法可以通过trunk访问文档?)。我的意思是,我完全支持自己动手,但django在提供统一的做事方式方面非常出色(好吧,不管怎样,IMO)。签出该分支,确保安装了docutils和Sphinx,然后进入docs/目录并运行“make html”。这应该像Django网站上的文档一样以HTML格式构建文档,您可以在本地访问它们。好的,我已经阅读了源代码(特别是
models/fields/\uuuu init\uuuuuuu.py
、models/base.py和core/validators.py),因为到目前为止的文档没有提到模型验证。但是,应该注意,它的工作原理与表单验证几乎相同(至少,一般逻辑或多或少是相同的)。不管怎样,这是我一直在寻找的东西。我只是希望如果我从主干切换到这个分支,我的应用不会坏得很厉害。我当然很乐意帮助django。而且,由于缺乏文档,我不得不求助于代码潜水,这在django的案例中根本不是一种不愉快的经历,它让我对事情的运作有了坚实的理解(尽管这需要一些时间)。顺便说一句,没有什么东西真的坏了,验证部分确实起作用了。它仍然不能回答问题。。。好的,现在有一个地方可以放置模型验证。。。除了它仅在使用ModelForm时运行!!!因此,问题仍然是“当有必要确保[任何验证]在db级别得到尊重时”,您应该怎么做?哪里叫“完全清洁”?不,不是真的。模型验证目前在django stable中,所以原始问题的重点是mootI不这么认为,因为保存时验证程序不会运行,所以它将允许您添加未验证的内容。从“简单地调用模型实例的save()方法将不会对实例的数据执行任何验证”开始,虽然我可能误解了OP的意图,但我肯定希望有一种保存的方法