【问题标题】:A pythonic way to solve the following implementation解决以下实现的pythonic方法
【发布时间】:2012-05-27 23:43:53
【问题描述】:

我的 django 应用中有 3 个模型

class Company(models.Model):

    name = models.CharField(_("Name"), max_length = 100, blank = True, null = True)
    address = models.CharField(_("Address"), max_length = 300, blank = True, null = True)

class WebSite(models.Model):

    WEBSITE_TYPE_CHOICES = (
        ('Google+', 'Google+'),
        ('Facebook', 'Facebook'),
        ('Orkut', 'Orkut'),
    )
    user = models.ForeignKey(User)
    website = models.URLField(blank = True, null = True)
    website_type = models.CharField(max_length = 15, choices = WEBSITE_TYPE_CHOICES, default = 'Google+')
    company = models.ForeignKey(Company, null=True, blank=True)

class Review(models.Model):

    rating = models.FloatField(blank = True, null = True) 
    review = models.TextField(blank = True, null = True)
    company = models.ForeignKey(Company, null=True, blank=True)
    website = models.ForeignKey(Website, null=True, blank=True)

我想显示我的数据比如

A公司:

  1. Google - 5 条评论,平均 3.4 条
  2. Orkut - 9 条评论,平均 4.1
  3. Facebook - 12 条评论,平均 4.3
  4. 任何其他 - 2 条评论,平均 2 条

公司B:

  1. Google - 2 条评论,平均 3 条
  2. Facebook - 5 条评论,平均 4 条

为此我已经完成了

    final_list = company_list = []
    websites = Website.objects.select_related().filter(user = user)

    for website in websites:
        company = website.company
        if company is not None and company not in company_list:
            company_list.append(brand)
            company_websites = websites.filter(company = company)
            info = []
            for company_website in company_websites:
                company_type = company_website.website_type
                reviews = Review.objects.filter(company = company, website = company_website)
                no_of_reviews = len(reviews)
                average = reviews.aggregate(Avg('rating'))
                info.append({"type": company_type, "no_of_reviews": no_of_reviews,
                             "average": average['rating__avg']})
            final_list.append({"company": company.name, "stats": info})

代码有2个问题

  1. 这是在浪费大量的计算
  2. 它还会以某种方式在 final_list 中附加空列表 (BUGGY)

仅供参考:我相信 .annotate() 可以使用,但我不明白如何根据列使用它,在我的情况下是 (company__name)

【问题讨论】:

  • 您希望final_list 和company_list 完全相同吗?如果没有,请将第一行分成两行。在 Python 中,列表的变量名最终是指向内存中列表元素的指针。因此,在您的代码中,final_list 和 company_list 都指向同一个列表。
  • 最初在 ORM 中寻找一些灵活的东西
  • 我只是在发表评论。不要写... final_list = company_list = [],除非您希望它们保持相同。
  • 我看不到 website.brand 是在哪里创建的或者它指的是什么。
  • 是的,这是一个错误。请立即查看

标签: django python django-orm


【解决方案1】:

这将为您提供数据。

Review.objects.values(company, website__website_type).annotate(review_count=Count('id'), average=Avg('rating')).order_by('company')

使用{% regroup %}在模板中输出。

【讨论】:

    【解决方案2】:

    我没有对此进行测试,它可能不如您收到的其他答案那么好,但如果它有帮助的话......

    companies = Company.objects.all()
    company_ratings = []
    
    for company in companies:
        websites = company.website_set.filter(user=user)
        new_data = []
    
        for website in websites:
            reviews = Reviews.objects.filter(website=website, company=company)
            ratings = [x.rating for x in reviews]
            count = len(ratings)
            new_data.append({'website': website, 'count': count, 
                             'average': float(sum(ratings))/count})
    
        company_ratings.append({'company':company, 'ratings':new_data})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-20
      • 1970-01-01
      相关资源
      最近更新 更多