Django извлекает родственного ребенка из родительского объекта - PullRequest
1 голос
/ 23 декабря 2019

Я использую Django 2.2, и у меня есть модель с двумя классами Product и ProductRevision. Когда я получаю Product или список Product с, я всегда получаю соответствующий ProductRevision. ProductRevision объекты увеличиваются, и только последняя ревизия должна быть выбрана с Product.

class Product(models.Model):
    name = models.CharField(max_length=50, null=False, blank=False,
                            verbose_name=_("name"))
    product_code = models.CharField(max_length=10, null=False, blank=False,
                                    verbose_name=_("product code"))
    slug = models.SlugField(null=False, unique=True)

    @property
    def current_item(self):
        return ProductRevision.objects.filter(product=self, active=True).order_by('-version').first()


class ProductRevision(models.Model):
    product = models.ForeignKey(Product, null=True, on_delete=models.PROTECT)
    version = models.IntegerField(default=0,
                                  verbose_name=_("version"))
    active = models.BooleanField(default=False, null=False, blank=True,
                                 verbose_name=_("is active"))
    qty_close = models.IntegerField(default=0,
                                    verbose_name=_("qty of accounts to be closed"))
    price_eur = models.DecimalField(max_digits=6, decimal_places=2, default=0,
                                    verbose_name=_("price in EUR"))

Я попытался добавить свойство current_item, чтобы получить последнюю ревизию данного продукта. Хотя это работает, это очень неэффективно, потому что когда я использую его в шаблоне, он попадает в базу данных каждый раз, когда я отображаю поле из связанной ProductRevision.

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

1 Ответ

1 голос
/ 23 декабря 2019

Мне удалось добиться чего-то подобного с помощью пользовательского набора запросов, связанных с предварительной выборкой

products = Product.objects.prefetch_related(Prefetch(
    'productrevision_set',
    queryset=ProductRevision.objects.order_by('product', '-version').distinct('product'),
    to_attr='latest_revision'
))

Приведенный выше набор запросов будет возвращать только один ProductRevision на Product, что вЭффект дает нам самые последние ProductRevision для всех Products всего за 2 запроса

for product in products:
    for latest_revision in product.latest_revision:
        print(product, latest_revision)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...