【问题标题】:How do I get the top-ranked products within a category?如何获得一个类别中排名靠前的产品?
【发布时间】:2012-07-18 14:43:04
【问题描述】:

给定一个产品(product_name 是视图中的一个参数),我试图返回该类别中排名靠前的 5 个产品(由方法“get_avg_rating”定义)作为我可以循环遍历的列表模板。有关如何执行此操作的任何建议?

class Productbackup(models.Model):
    website = models.CharField('Product name', max_length = 200)
    url_friendly = models.CharField('URL friendly', max_length = 200)
    website_url = models.URLField('Product URL')
    description= models.CharField('Description', max_length = 2000)
    category = models.ForeignKey(Categories)
    #category = models.ManyToManyField(Categories)
    image_hero = models.URLField('Hero image url')
    image_second = models.URLField('Second image url')
    image_third = models.URLField('Third image url')
    created_on = models.DateTimeField(auto_now_add = True)
    updated_at = models.DateTimeField(auto_now = True)
    def __unicode__(self):
        return self.website

    def get_avg_rating(self):
        reviews = Reviewbackup.objects.filter(product=self)
        count = len(reviews)
        sum = 0.0
        for rvw in reviews:
            sum += rvw.rating
        return (sum/count)

    def get_num_reviews(self):
        reviews = Reviewbackup.objects.filter(product=self)
        count = len(reviews)
        return count

RATING_OPTIONS = (
    (1, '1'),
    (2, '2'),
    (3, '3'),
    (4, '4'),
    (5, '5'),
                (6, '6'),
    (7, '7'),
    (8, '8'),
    (9, '9'),
    (10, '10'),
)
class Reviewbackup(models.Model):
    review = models.CharField('Review', max_length = 2000)
    created_on = models.DateTimeField(auto_now_add = True)
    updated_at = models.DateTimeField(auto_now = True)
    user = models.CharField('Username', max_length =  200)
    rating = models.IntegerField(max_length=2, choices=RATING_OPTIONS)
    product = models.ForeignKey(Productbackup)
    def __unicode__(self):
        return self.review

class Categories(models.Model):
    category = models.CharField('Category_second', max_length = 200)
        url_friendly = models.CharField('url_friendly', max_length = 200)
    def __unicode__(self):
        return unicode(self.category)

def view_reviews(request, product_name):
    product = get_object_or_404(Productbackup, url_friendly=product_name)
    product_id = product.id
    #get reviews for the this product
    reviews = Reviewbackup.objects.filter(product_id=product_id).order_by("-created_on")
    #similar products in category comparison
    prod_category = Productbackup.objects.filter(category=product.category)
    #top_ranked = Productbackup.objects.order_by('get_avg_rating')[0:5]
    #recently added
    recent_added = Productbackup.objects.order_by('-created_on')[0:5]
    return render_to_response('reserve/templates/view_reviews.html', {'prod_category': prod_category, 'product':product, 'reviews':reviews, 'recent_added':recent_added},
    context_instance=RequestContext(request))

【问题讨论】:

    标签: django view methods models


    【解决方案1】:

    您可以为此使用annotate

    from django.db.models import Sum, Avg
    
    def get_top_products(amount=5):
        try:
             Productbackup.objects.annotate(review_amount=Sum("reviewbackup__product")).\
                                   order_by("review_amount")[:amount]
        except Productbackup.DoesNotExist:
            return None
    

    这只是一个基本示例,可以根据您的需要进行扩展

    【讨论】:

      【解决方案2】:

      尝试实现:

      创建字典。它将 Product 作为键,将评级作为值。

      遍历您的项目 (Product.objects)

      在该循环中,将每个项目放入字典中

      在该循环之外,按值对字典进行排序。 (见Sort a Python dictionary by value

      获取字典的最后一项 (dictionary[-5])。

      请注意,您必须处理具有同等评级的项目。确实,如果 10 个项目的分数相同,那么使用上述方法,您的 Top 5 没有任何意义。

      这会产生类似这样的代码:

      items_with_rating = {}
      for product in Product.objects:
          items_with_rating[product] = product.get_avg_rating()
      
      items_sorted_by_rating = sorted(items_with_rating.iteritems(), key=operator.itemgetter(1))
      
      top5_items = items_sorted_by_rating[-5]
      

      【讨论】:

      • 我发现这个解决方案的问题是排序字典(top5_items)不允许我访问产品的其他属性,例如描述和类别。它只返回一个包含产品名称和评级的字典。关于如何访问模板中的其他属性的任何想法?
      • 我不想粗暴,但问题是在玩 Django 之前你需要学习 Python 语言的基础知识。字典键是您的产品对象,而不是字符串。顺便说一句,你应该选择更好的类名。
      【解决方案3】:

      也许这样的东西可以工作?

      products = [[prod, prod.get_avg_rating()] for prod in Productbackup.objects()]
      
      top_5_items = sorted(products, key=lambda x: x[1], reverse=True)[:5]
      

      【讨论】:

      • 你不只是重写/总结我的答案吗?
      • 嗯,有多种方法可以解决这个问题,而我的只是用更少的代码行,尽管结果是一样的。
      猜你喜欢
      • 2021-09-13
      • 2021-08-12
      • 2013-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-04
      • 2011-12-08
      相关资源
      最近更新 更多