Построить Django "ForeignKey", который возвращает несколько значений
Я хотел бы создать новый связанный тип поля. Вот простой пример:
class CustomQuerySet(QuerySet):
def current(self):
return self.filter(invalid_date__isnull=True)
class CustomManager(Manager):
def get_query_set(self):
return CustomQuerySet(self.model, using=self._db)
def current(self):
return self.get_query_set().current()
class Item(models.Model):
objects = CustomManager()
row_id = models.IntegerField(primary_key=True)
id = models.IntegerField()
name = models.CharField(max_length=100)
change_date = models.DateTimeField(auto_now_add=True)
invalid_date = models.DateTimeField(null=True, blank=True)
class Collection(models.Model):
item = MultipleRelatedField(Item, related_field='id', related_name='collections')
name = models.CharField(max_length=100)
Дано c = Collection()
:
c.item
должен вернуть набор запросов, эквивалентныйItem.objects.filter(id=c.item_id)
,- Этот набор запросов должен быть экземпляром CustomQuerySet
Item.objects.filter(collections__name='SomeName')
должен работать как положено.- Операция
Collection.objects.filter(item__name='OtherName', item__invalid_date__isnull=True)
должен работать как положено.
Я понимаю, что это может быть реализовано с ManyToManyField
но я не хочу вручную добавлять / удалять объекты предметов в c.item. Мне не нужна таблица соединений, поскольку c.item всегда использует одно значение id, это просто не первичный ключ в Collection. А также c.item
может / не / содержать объекты предметов с разными значениями идентификатора.
Я знаю, что это, вероятно, будет требовать подклассов django.db.models.fields.related.ForeignRelatedObjectsDescriptor
и / или django.db.models.fields.related.ForeignObject
(или, возможно, эквиваленты ManyToMany).
1 ответ
Мне кажется, что вы действительно хотите, это автоматический способ создания набора запросов из модели A
против другой модели B
основанный на значении поля в A
,
Я подозреваю, что в конечном итоге, возвращая этот набор запросов в качестве значения поля на A
на самом деле это не лучшее решение - это действительно идет вразрез с ORM и затруднит, например, использование этой модели в админке или других местах общего пользования.
Вместо этого было бы лучше взять идею из того, как Django обрабатывает поля с choices
set: автоматически генерировать метод в классе модели, который возвращает производную информацию, например, если ваша модель имеет поле:
item = MultipleRelatedField(Item, related_field='id', related_name='collections')
вы бы автоматически получили такой метод, как get_item_queryset
это вернет указанный вами набор запросов.
Чтобы построить это, вы, вероятно, захотите создать подкласс существующего поля (IntegerField
будет хорошей отправной точкой), а затем переопределить __init__
метод (чтобы принять дополнительные аргументы) и contribute_to_class
метод (где новый метод будет создан). Вы можете увидеть место, где это происходит для choices
-derived get_FIELD_display
метод здесь для вдохновения.