Django 1.8.3 - 使用相关对象进行模型字段验证

Kho*_*eir 6 python django foreign-keys django-admin

对于以下模型集(Foo,Bar),您可以将以下代码段的Bar.clean中的交叉验证规则强加到django 1.7.

相同的代码片段RelatedObjectDoesNotExist在django 1.8.3中引发错误.

在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.')
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

Ser*_*jik 1

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

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

  if self.name + self.foo.name != 'FooBar':
     raise ValidationError('Concatenation should be FooBar.')
Run Code Online (Sandbox Code Playgroud)

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

现在我已经使用 Django 1.8.x 测试了代码,并且出现了异常,正如您提到的,这就是结果:

{'_state': <django.db.models.base.ModelState object at 0x7ff55cd30710>, 'id': None, 'foo_id': None, 'name': 'Bar 1'}
Run Code Online (Sandbox Code Playgroud)

现在我用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>}
Run Code Online (Sandbox Code Playgroud)

正如您可能注意到的,foo_id在这两种情况下,None但神奇之处在于_foo_cacheDjango 1.8 中被删除的东西

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

进行了这些更改:ad​​min.py

class BarInline(admin.TabularInline):
    model = Bar
    form = BarForm
Run Code Online (Sandbox Code Playgroud)

表格.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.')
Run Code Online (Sandbox Code Playgroud)