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

发布于 2024-09-14 22:21:32 字数 1347 浏览 7 评论 0原文

我以前有这样的模型:

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(通过内联附加)只能具有其类型属性的值的子集,具体取决于父程序集。

这效果很好。

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

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 。

有什么办法解决这个问题吗?我这样做错了吗?

感谢您的帮助。

I previously had models like this:

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.')

The effect was, a new AssemblyAnnotation (attached via an inline) could only have a subset of values for it's type attribute, depending on the parent Assembly.

This worked great.

Now, it has come time to apply these annotations to other objects that are slightly different:

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.')

As you can see, I want the same rules applied. However, there is a problem. The GenericInline that I am now using does not set self.content_type before my clean() method is run.

Is there any way around this? Am I doing this wrong?

Thanks for the help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

明媚殇 2024-09-21 22:21:32

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

我认为您需要执行 if self.content_type in ContentType.objects.get_for_model(Assembly):

Wouldn't the right hand side return a list in
if self.content_type == ContentType.objects.get_for_model(Assembly):?

I would think you would need to do if self.content_type in ContentType.objects.get_for_model(Assembly):

几味少女 2024-09-21 22:21:32

我用的和你一样,效果也符合预期。这是我的代码:

在模型中:

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)没有设置。

I'm using the same as you and it works as espected. Here's my code:

In the Models:

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.')

And in the Admin:

class GroupFlagIntermediateInline(admin.TabularInline):
    model = GroupFlagIntermediate

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

admin.site.register(GroupFlag, GroupFlagAdmin)

After some tests, I found that the content_type and object_id (flag_pk in my case) fields are set before the clean() call, but the GenericForeignKey (flag in my case) doesn't.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文