首页 > 解决方案 > Django - 获取每个关系中的最新对象

问题描述

假设我的Product项目中有一个模型:

class Product(models.Model):
    price = models.IntegerField()

我想要一些统计数据(假设我想跟踪价格随时间的变化):

class ProductStatistics(models.Model):
    created = models.DateTimeField(auto_add_now=True)
    statistics_value = models.IntegerField()
    product = models.ForeignKey(Product)

    @classmethod
    def create_for_product(cls, product_ids):
        statistics = []
        products = Product.objects.filter(id__in=products_ids)
        for product in products:
            statistics.append(
                product=product
                statistics_value=product.price
            )
        cls.objects.bulk_create(statistics)

    @classmethod
    def get_latest_by_products_ids(cls, product_ids):
        return None

我对实施get_latest_by_products_ids方法有疑问。我只想要最新的统计数据,所以我不能做类似的事情:

    @classmethod
    def get_latest_by_products_ids(cls, product_ids):
        return cls.objects.filter(product__id__in=product_ids)

因为这将返回我通过时间收集的所有统计数据。如何将查询限制为每个产品的最新查询?

编辑 我正在使用 PostgreSQL 数据库。

标签: djangopostgresqldjango-orm

解决方案


查询集已经有一个last()方法(而且first()FWIW 也有一个方法)。唯一的问题是您要定义为“最后一个”,因为这取决于查询集的顺序......但假设您想要最后一个创建日期(created字段),您也可以使用该lastest()方法

@classmethod
def get_latest_by_products_ids(cls, product_ids):
    found = []
    for pid in products_ids:
        found.append(cls.objects.filter(product_id=pid).latest("created"))
    return found

附带说明:Django 的编码风格是使用Manager(并最终使用Queryset)对整个表进行操作,因此您应该创建一个自定义管理器,而不是在您的模型上创建类方法:

class productStatisticManager(models.Manager):

    def create_for_products(self, product_ids):
        statistics = []
        products = Product.objects.filter(id__in=products_ids)
        for product in products:
            statistics.append(
                product=product
                statistics_value=product.price
            )
        self.bulk_create(statistics)

    def get_latest_by_products_ids(cls, product_ids):
        found = []
        for pid in products_ids:
           last = self.objects.filter(product_id=pid).latest("created")         
           found.append(last)
        return found

class ProductStatistics(models.Model):
    created = models.DateTimeField(auto_add_now=True)
    statistics_value = models.IntegerField()
    product = models.ForeignKey(Product)

    objects = ProductStatisticManager()

推荐阅读