1

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

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)应按预期工作。

我意识到这可以用 a 来实现,ManyToManyField但我不想手动将项目对象添加/删除到 c.item。我不需要连接表,因为 c.item 总是使用单个 id 值,它不是 Collection 上的主键。并且c.item可能/不/包含具有不同 id 值的项目对象。

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

4

1 回答 1

1

在我看来,您真正想要的是一种自动方法,可以A根据.BA

我怀疑最终,将该查询集作为字段的值返回A并不是真正的最佳解决方案——这确实违背了 ORM 的原则,并且会使例如在管理员中使用该模型或其他常见的地方。

相反,最好从 Django 如何处理带有choicesset 的字段中获取一个想法:在模型类中自动生成一个返回派生信息的方法,例如,如果您的模型有一个字段:

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

您将自动获得一个类似的方法,该方法get_item_queryset将返回您指定的查询集。

要构建它,您可能希望对现有字段进行子类化(IntegerField可能是一个很好的起点),然后覆盖__init__方法(以接受其他参数)和contribute_to_class方法(将生成新方法的位置)。您可以在此处查看-derived方法发生这种情况choicesget_FIELD_display地方以获取灵感。

于 2014-02-14T20:28:25.433 回答