使用annotate()包含django模型对象属性

N61*_*51H 0 django model properties annotate django-queryset

我有一个模型,其中包含一个@property当我做类似 vals = MyModel.objects.values() S / O帖子之类的事情时要包含 的模型,建议这样做的get_queryset方法是通过覆盖manager类的方法,并增加对的调用annotate(xtra_field=...)

问题是我找不到如何使用模型属性执行此操作的示例。我已经尝试过类似的东西 super(SuperClass, self).get_queryset().annotate(xtra_fld=self.model.xtra_prop) 及其众多变体,但都无济于事。

我认为问题是注释参数的RHS应该是什么?

(而且,是的,我知道还有其他更笨拙的方法可以做到这一点,例如遍历values()返回的收益并随便添加属性。对我来说,这不是一个非常优雅(甚至是Django)的解决方案。

dam*_*mon 5

除非您要在数据库中生成属性值,否则,如果不重写django的内部方法(我建议不要使用),就无法做到这一点  。

一个更优雅的解决方案可能是向自定义查询集添加一个额外的方法,方法可应要求生成额外的字段:

from django.db import models

class AreaQuerySet(models.QuerySet):
    def values_with_area(self, *fields):
        # width & height are always required to calculate the area
        fields = set(fields)
        fields.update(['width', 'height'])

        for row in self.values(*fields):
            row['area'] = Widget.calculate_area(row['width'], row['height'])
            yield row

class Widget(models.Model):
    # ...
    objects = AreaQuerySet.as_manager()

    @classmethod
    def calculate_area(cls, width, height):
        return width * height

    @property
    def area(self):
        return Widget.calculate_area(self.width, self.height)
Run Code Online (Sandbox Code Playgroud)

  • 像这样的东西可能会起作用。但是,我觉得这是一个更复杂的解决方案。我希望它是某种语义,例如双下划线。也就是说:``...annotate(xtra_field='self__xtraproperty')``。它“应该”就是这么简单。 (4认同)
  • 我认为您是要在Widgets模型中引用AreaQuerySet作为管理器。 (2认同)