Django 1.8.3 - 具有相关对象的模型字段验证

Posted

技术标签:

【中文标题】Django 1.8.3 - 具有相关对象的模型字段验证【英文标题】:Django 1.8.3 - model field validation with related object 【发布时间】:2015-10-01 00:45:12 【问题描述】:

对于以下一组模型(Foo、Bar),您可以施加交叉验证规则,如以下代码 sn-p 至 django 1.7 的 Bar.clean 中的规则。

同样的 sn-p 在 django 1.8.3 中抛出 RelatedObjectDoesNotExist 错误。

在 django 1.8.3 中实现相同结果的新改进方法是什么?

(我包含 admin.py 代码只是为了展示这些模型的使用方式。)

models.py

from django.db import models
from django.core.exceptions import ValidationError

class Foo(models.Model):
   name = models.CharField("Name", blank=True, max_length=300)

class Bar(models.Model):
   name = models.CharField("Name", blank=True, max_length=300)
   foo = models.ForeignKey('Foo', verbose_name='Foo')

   def clean(self):
      if self.name + self.foo.name != 'FooBar':
         raise ValidationError('Concatenation should be FooBar.')

admin.py

from django.contrib import admin
import models

class BarInline(admin.TabularInline):
    model = models.Bar

class FooAdmin(admin.ModelAdmin):
    model = models.Foo
    inlines = [BarInline,]

site = admin.site
site.register(models.Foo,FooAdmin)

【问题讨论】:

【参考方案1】:

我在您的代码中添加了一个简单的输出修改

def clean(self):
  print(self.__dict__)

  if self.name + self.foo.name != 'FooBar':
     raise ValidationError('Concatenation should be FooBar.')

简单的打印语句将在执行主代码之前打印出 Bar 对象。

现在我已经用 Django 1.8.x 测试了代码,我得到了你提到的异常结果:

'_state': <django.db.models.base.ModelState object at 0x7ff55cd30710>, 'id': None, 'foo_id': None, 'name': 'Bar 1'

现在我用 Django 1.7.x 再次测试了它,它工作正常,输出结果是:

'_foo_cache': <Foo: Foo object>, 'name': 'Bar 1', 'id': None, 'foo_id': None, '_state': <django.db.models.base.ModelState object at 0x7f731151c9e8>

您可能会注意到None 在这两种情况下的foo_id,但神奇的是在Django 1.8 中删除的_foo_cache 东西

我可以建议您的替代方法是将您的验证移到表单中

进行了以下更改: 管理员.py

class BarInline(admin.TabularInline):
    model = Bar
    form = BarForm

forms.py

class BarForm(forms.models.ModelForm):
    class Meta:
        model = Bar
        fields = ('name',)

    def clean(self):
      data = self.cleaned_data     
      if not data['name'] + data['foo'].name == "foobar":
         raise ValidationError('Concatenation should be FooBar.')

【讨论】:

这个自省非常有用,谢谢。您是否知道为什么 Django 开发人员会从模型 clean() 方法中删除查询相关对象的功能,这似乎很方便?

以上是关于Django 1.8.3 - 具有相关对象的模型字段验证的主要内容,如果未能解决你的问题,请参考以下文章

Django - 以一对多关系更改相关对象的值

Django:获取具有至少一个相关模型的模型的子集

django相关查询过滤器,搜索有无相关项目的项目

Django 模型 - 相关对象验证

删除 django 模型中不相关的对象(manytomanyfield)

Django:无法创建与一个普通模型具有一对一关系的多个模型对象