借助http://localhost:8080/api/files/file-id,我可以轻松访问需要拥有通用外键的所有模型。显然,这不是我想要的。我想将其限制为我拥有的模型的子集-特别是抽象模型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', )
}),
]
答案 0 :(得分: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
现在,我们可以定义一个callable来获取作为类的子类的ContentType
的主键,在本例中为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
然后在ForeignKey
到ContentType
中,我们可以使用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