Включите свойство объекта модели django, используя annotate () - PullRequest
0 голосов
/ 18 мая 2018

У меня есть модель, включающая @property, которую я хочу включить, когда я делаю что-то вроде vals = MyModel.objects.values() Еще один пост S / O предлагает способ сделать это путем переопределения метода get_querysetкласса менеджера, дополненного вызовом annotate(xtra_field=...).

Проблема в том, что я не могу найти пример того, как сделать это с помощью свойства модели.Я пробовал такие вещи, как super(SuperClass, self).get_queryset().annotate(xtra_fld=self.model.xtra_prop) и их многочисленные варианты, ни один из которых не работает.

Мне кажется, вопрос в том, какой должна быть RHS аргумента (ов) аннотации?

(И да, я знаю, что есть и другие, более неуклюжие способы сделать это, например, повторять то, что возвращает values(), и добавлять свойство по ходу работы. Просто для меня это не очень элегантное (или даже django) решение.

1 Ответ

0 голосов
/ 18 мая 2018

Если вы не генерируете значение свойства в базе данных, вы не сможете сделать это, не переопределив внутренние методы 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)
...