首页 > 解决方案 > 如何在 django 详细视图中获取每个选项的总票数?

问题描述

我正在开发一个基于 Django 的餐厅评论网站。当用户发送评论时,他们填写一个包含两个选择字段的表单。目前,我可以在 Detailview 页面中显示特定餐厅的所有评论。我想从评论表单的选择字段中获取信息,以便在详细视图(1 家特定餐厅)和列表视图(列出的所有餐厅)中为用户显示此数据:

问题:

  1. 我想获得每个选择的“投票”总数,并在详细视图中显示它,例如 Chart Js。在 django 中首选的方式或这样做是什么?我曾尝试在 javascript 中进行此过滤,但是我知道这可以直接在模型或视图中更有效地完成。

代码
模型.py

class Restaurant(models.Model): 
      name        = models.CharField(max_length = 100)

class Comment(models.Model):
      STATUS_1 = (
               ('one', 'one'),
               ('two', 'two'),
               ('three', 'three'),
       ) 
       STATUS_2 = (
               ('cheap', 'cheap'),
               ('normal', 'normal'),
               ('expensive', 'expensive'),
       ) 
       restaurant = models.ForeignKey(Restaurant, on_delete = models.CASCADE, related_name='comments')
       comment    = models.TextField(max_length = 500)
       status_1   = models.CharField(max_length = 100, choices=STATUS_1)
       status_2   = models.CharField(max_length = 100, choices=STATUS_2)

视图.py

class RestaurantDetailView(DetailView):
    model = Restaurant
    form_class = CommentForm
    template_name = 'core/restaurant_detail.html'

def get_context_data(self, **kwargs):
    context = super(RestaurantDetailView, self).get_context_data(**kwargs)
    comment_form = CommentForm
    context['comment_form'] = comment_form
    return context

def point_dataset(self, request):
    points = serialize('geojson', Restaurant.objects.all())
    return HttpResponse(points, content_type='json')


def get_queryset(self):
    return Restaurant.objects.annotate(avg_rating=Avg('comments__rate'))

例如:
如果某家餐厅有 3 条评价结果:STATUS_1 = 'one', 'one', 'two' and STATUS_2 = 'normal', 'cheap', 'normal',我如何将以下数据传递给图表js:
STATUS_1:['一':'2','二':'1','三':'0']
STATUS_2:['便宜':'1','正常':'2','昂贵的':'0']

标签: djangodjango-modelsdjango-views

解决方案


最简单的解决方案是使用collection.Counter. 例如,在您的模型中添加一个属性方法:

from collections import Counter

class Restaurant(models.Model):
    ...
    @property
    def status_1(self):
      return Counter(list(self.comments.values_list('status_1',flat=True)))

    @property
    def status_2(self):
      return Counter(list(self.comments.values_list('status_2',flat=True)))

为了减少数据库命中,您可以使用prefetch_related预加载评论查询集:

def get_queryset(self):
    return Restaurant.objects.annotate(avg_rating=Avg('comments__rate')).prefetch_related('comments')

模板中的用法应该是这样的:

{{ restaurant.status_1 }}
{{ restaurant.status_2 }}

要获取键和值,您可以这样尝试:

{{ restaurant.status_1.keys }}
{{ restaurant.status_1.values }}

基本上它就像一本字典。


推荐阅读