Django inlinemodeladmin 验证 - 但具有通用关系

Posted

技术标签:

【中文标题】Django inlinemodeladmin 验证 - 但具有通用关系【英文标题】:Django inlinemodeladmin validation - but with a generic relation 【发布时间】:2011-04-01 18:31:02 【问题描述】:

我以前有这样的模型:

class AssemblyAnnotation(models.Model):
    assembly = models.ForeignKey(Assembly)
    type = models.ForeignKey(AssemblyAnnotationType)
    ...
    def clean(self):
        from django.core.exceptions import ValidationError
        if not self.type.can_annotate_aliases and self.assembly.alias_of_id is not None:
            raise ValidationError('The selected annotation type cannot be applied to this assembly.')

效果是,新的 AssemblyAnnotation(通过内联附加)只能具有其类型属性的值的子集,具体取决于父 Assembly。

效果很好。

现在,是时候将这些注释应用于其他略有不同的对象了:

class ObjectAnnotation(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey()
    type = models.ForeignKey(AssemblyAnnotationType)
    ...
    def clean(self):
        from django.core.exceptions import ValidationError
        if self.content_type == ContentType.objects.get_for_model(Assembly):
            if not self.type.can_annotate_aliases and self.content_object.alias_of_id is not None:
                raise ValidationError('The selected annotation type cannot be applied to this assembly.')

如您所见,我希望应用相同的规则。但是,有一个问题。我现在使用的 GenericInline 在我的 clean() 方法运行之前没有设置 self.content_type。

有没有办法解决这个问题?我做错了吗?

感谢您的帮助。

【问题讨论】:

【参考方案1】:

右侧不会返回一个列表 if self.content_type == ContentType.objects.get_for_model(Assembly):?

我认为你需要做if self.content_type in ContentType.objects.get_for_model(Assembly):

【讨论】:

不,get_for_model returns a single ContentType object。无论如何,这不是问题。问题是 GenericInline 在调用 clean() 之前没有设置 content_type。【参考方案2】:

我使用的和你一样,它的工作原理和预期的一样。这是我的代码:

在模型中:

class GroupFlagIntermediate(models.Model):
    group_flag = models.ForeignKey(GroupFlag, related_name='flag_set')
    content_type = models.ForeignKey(ContentType, verbose_name='Flag Type')
    flag_pk = models.CharField('Flag PK', max_length=100, blank=True, default='')
    flag = generic.GenericForeignKey('content_type', 'flag_pk')

    def clean(self):
        from django.core.exceptions import ValidationError
        if not self.is_valid_flag(self.content_type.model_class()):
            raise ValidationError('The selected flag is not a real Flag.')

在管理员中:

class GroupFlagIntermediateInline(admin.TabularInline):
    model = GroupFlagIntermediate

class GroupFlagAdmin(admin.ModelAdmin):
    list_display = ('name', ...)
    inlines = [GroupFlagIntermediateInline]

admin.site.register(GroupFlag, GroupFlagAdmin)

经过一些测试,我发现content_typeobject_id(在我的情况下为flag_pk)字段是在 clean() 调用之前设置的,但GenericForeignKey(在我的情况下为flag)没有不。

【讨论】:

以上是关于Django inlinemodeladmin 验证 - 但具有通用关系的主要内容,如果未能解决你的问题,请参考以下文章

Django InlineModelAdmin:部分显示内联模型并链接到完整模型

InlineModelAdmin对象的学习

显示嵌套模型的InlineModelAdmin

如何从管理上下文数据中找到InlineModelAdmin?

luffy之极验短信验证(多条件登录)

使用 Django 1.8 的 show_change_link,“保存”按钮返回错误页面