构建一个返回多个值的Django“ForeignKey”

时间:2014-02-14 18:42:57

标签: django django-orm django-related-manager

我想建立一个新的相关字段类型。这是一个简单的例子:

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可能/不包含具有不同id值的项目对象。

我知道这可能需要继承django.db.models.fields.related.ForeignRelatedObjectsDescriptor和/或django.db.models.fields.related.ForeignObject(或者可能是ManyToMany等价物)。

1 个答案:

答案 0 :(得分:1)

在我看来,您真正想要的是根据A中字段的值,从模型B生成针对其他模型A的查询集的自动方式。

我怀疑最终,将该查询集作为A上的字段值返回并不是最好的解决方案 - 这实际上违背了ORM的内容并且会使其变得困难,例如,在管理员或其他常见地方使用该模型。

相反,最好从Django如何处理具有choices集的字段中获取一个想法:在模型类中自动生成一个返回派生信息的方法,这样如果你的模型有一个字段: / p>

item = MultipleRelatedField(Item, related_field='id', related_name='collections')

你会自动获得一个像get_item_queryset这样的方法来返回你指定的查询集。

要构建它,您可能希望子类化现有字段(IntegerField可能是一个很好的起点),然后覆盖__init__方法(接受其他参数)和{ {1}}方法(将生成新方法)。你可以看到the choices-derived get_FIELD_display method here获得灵感的地方。