【问题标题】:How to fetch the top two products for each product type?如何获取每种产品类型的前两个产品?
【发布时间】:2010-11-24 08:32:26
【问题描述】:

假设我有两个看起来像这样的模型:

类产品类型(模型。模型): product_type = models.CharField(max_length=100) 类产品(模型。模型): 名称 = models.CharField(max_length=200) 蛞蝓 = 模型.SlugField() product_type = models.ForeignKey(ProductType) score = models.PositiveIntegerField(default=0)

现在我想从每个 ProductType 中获取前两个产品(得分最高的两个)。 因此,如果我有 Phones, Computers, TVs 作为 ProductTypes,我想要两个最好的 Phones, Computers, TVs。

由于我什至不知道如何在 MySQL 中执行此操作,因此我尝试搜索 MySQL 解决方案,但我发现的解决方案非常复杂,而且这并不是一件非常复杂的事情。

我倾向于为顶级产品制作自己的模型,并有一个 cronjob 来解决这个问题,但我想看看是否有更简单的解决方案。

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    好吧,您可以在 ProductType 类中创建一个方法,返回其产品的前两个结果:

    class ProductType(models.Model):
        product_type = models.CharField(max_length=100)
    
        def TopTwoProducts(self):
            return self.product_set.order_by('-score')[0:2]
    

    然后你会做这样的事情:

    for type in ProductType.objects.all():
        type.TopTwoProducts()
    

    【讨论】:

    • 智能解决方案,我喜欢!谢谢。
    • 我不明白...你为什么使用 for 循环?
    • 只有在访问前两个产品时才使用 for 循环(例如在模板中列出它们或其他任何产品)。
    【解决方案2】:

    虽然 adam 的解决方案是正确的,但更类似于 django 的方式是使用管理器。

    在 James Bennett 的博客上查看 Managers versus class methods

    其他优点:

    • 管理器携带所有特定于查询的代码,同时避免混淆模型类
    • 同一个管理器类可以在多个类之间共享
    • 管理器可以直接在模型类上使用,也可以通过一对多或 m2m 关系使用

    因此,对于上述问题:

    from django.db import models
    from django.db.models.manager import Manager
    
    class ProductScoreManager(Manager):
    
        use_for_related_field = True
    
        def top_score(self, limit=2):
            return self.get_query_set().order_by('-score')[:limit]
    

    然后将此管理器类添加为产品的默认管理器

    class Product(models.Model):
        ...
        objects = ProductScoreManager()
        ...
    

    现在,由于 objects 覆盖了默认管理器,并且 use_for_related_field 允许在关系查询中使用它,top_score 方法可用于与产品相关的任何模型。

    myproducttype = ProductType.objects.get(...)
    myproducttype.products.top_score() # return top 2 products
    

    这允许更一致的语法:相关产品总是通过 products 访问,top_score 充当过滤器。此外,ProductType 类不再与 Product 的查询逻辑杂乱无章。

    【讨论】:

    • 谢谢,我明天再看看!
    【解决方案3】:

    只需从产品模型中过滤掉产品类型,像这样切片它们 -

        product_type_list = ProductType.objects.value("id")
        for product_type in product_type_list:
            Product.objects.filter(
                product_type=product_type
            ).order_by("-score")[0:2]
    

    【讨论】:

      猜你喜欢
      • 2022-12-12
      • 1970-01-01
      • 2020-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多