【问题标题】:GenericForeignKey in Grappelli admin: filter content_type to display only relevant modelsGrappelli admin 中的 GenericForeignKey:过滤 content_type 以仅显示相关模型
【发布时间】:2019-09-28 05:42:31
【问题描述】:

使用related lookups,我可以轻松访问我必须拥有通用外键的所有模型。显然,这不是我想做的。我想将其限制为我拥有的模型的子集——特别是从抽象模型Registry 继承的所有模型。

我的模型如下所示:

class Registry(models.Model):
    """A base registry class."""

    number = models.BigAutoField(primary_key=True)
    when = models.DateField(default=timezone.now)
    title = models.CharField(
        max_length=1024, default='', blank=True, null=True)

    class Meta:
        """The meta class."""

        abstract = True

    […]


class Revision(models.Model):
    """A revision model."""

    when = models.DateTimeField(default=timezone.now)
    identification = models.BigIntegerField()
    content_type = models.ForeignKey(
        ContentType, on_delete=models.CASCADE, related_name='+')
    object_id = models.PositiveIntegerField()
    parent = GenericForeignKey('content_type', 'object_id')

    […]


class Document(Registry):

    […]

class Drawing(Registry):

    […]

这样每个Registry 派生实例可以有许多不同的修订版。

以及相关管理员:

class RevisionAdmin(admin.ModelAdmin):
    """Revision administration definition."""

    fieldsets = [
        ('Revision', {
            'fields': [
                'when',
                'identification',
            ]
        }),
        ('Registry', {
            'classes': ('grp-collapse grp-open',),
            'fields': ('content_type', 'object_id', )
        }),
    ]

【问题讨论】:

    标签: django python-3.x django-grappelli


    【解决方案1】:

    您可以使用limit_choices_to [Django-doc]。由于您想将选择限制为后代,我们需要先编写一些额外的逻辑来计算这些:

    例如,我们可以先用this function计算所有子类:

    def get_descendants(klass):
        gen = { klass }
        desc = set()
        while gen:
            gen = { skls for kls in gen for skls in kls.__subclasses__() }
            desc.update(gen)
        return desc
    

    现在我们可以定义一个可调用对象来获取作为类的子类的ContentTypes 的主键,在本例中为Registry

    from django.db.models import Q
    from django.contrib.contenttypes.models import ContentType
    
    def filter_qs():
        if not hasattr(filter_qs_registry, '_q'):
            models = get_descendants(Registry)
            pks = [v.pk for v in ContentType.objects.get_for_models(*models).values()]
            filter_qs_registry._q = Q(pk__in=pks)
        return filter_qs_registry._q

    ForeignKeyContentType 中,我们可以使用limited_choices_to 字段:

    class Revision(models.Model):
        """A revision model."""
        when = models.DateTimeField(default=timezone.now)
        identification = models.BigIntegerField()
        content_type = models.ForeignKey(
            ContentType,
            on_delete=models.CASCADE,
            limit_choices_to=filter_qs_registry,
            related_name='+'
        )
        object_id = models.PositiveIntegerField()
        parent = GenericForeignKey('content_type', 'object_id')

    可变的上升次数

    我们可以概括上升次数,例如通过概括get_descendants 函数:

    def get_descendants(*klass):
        gen = { *klass }
        desc = set()
        while gen:
            gen = { skls for kls in gen for skls in kls.__subclasses__() }
            desc.update(gen)
        return desc
    

    接下来我们可以简单地调用它:

    from django.db.models import Q
    from django.contrib.contenttypes.models import ContentType
    
    def filter_qs():
        if not hasattr(filter_qs_registry, '_q'):
            models = get_descendants(Registry, OtherAbstractModel)
            pks = [v.pk for v in ContentType.objects.get_for_models(*models).values()]
            filter_qs_registry._q = Q(pk__in=pks)
        return filter_qs_registry._q

    【讨论】:

    • 只是另一个小补充:除了Registry 的后代之外,我如何向filter_qs 中的models 添加另一个类?
    • 酷。并且有了很大的改进。然而,我的意思是添加一个特定的其他模型——比如note——到列表中。不是Note 的后代,只是Note 本身。我尝试了models.update(Note),但得到了'ModelBase' object is not iterable...
    • @Sardathrion: you can use models.add(Note), .update(..) 表示你将一个可迭代对象(例如list)传递给函数。
    猜你喜欢
    • 2012-12-29
    • 2018-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-28
    • 2011-11-08
    • 2021-10-23
    相关资源
    最近更新 更多