Вы можете использовать limit_choices_to
[Django-doc] .Так как вы хотите ограничить выбор потомками , нам нужно написать некоторую дополнительную логику, чтобы сначала вычислить их:
Мы можем, например, сначала вычислить все подклассы с помощью thisfunction :
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
Теперь мы можем определить вызываемый объект для получения первичных ключей ContentType
s, которые являются подклассами класса, в данном случае 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(<b>Registry</b>)
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,
<b>limit_choices_to=filter_qs_registry</b>,
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(<b>Registry, OtherAbstractModel</b>)
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