【问题标题】:Django multiple filter in same table column同一表列中的 Django 多个过滤器
【发布时间】:2022-01-20 10:24:30
【问题描述】:

我想获取查询类型并显示该类型中每个产品的计数

在views.py中

def current(request):
    act=enquiry.objects.filter(type='Activity').values('product_name').distinct().annotate(Count('product_name'))
    wal=enquiry.objects.filter(type='Walkin').values('product_name').distinct().annotate(Count('product_name'))
    tele=enquiry.objects.filter(type='Tele').values('product_name').distinct().annotate(Count('product_name'))
    digital=enquiry.objects.filter(type='Digital').values('product_name').distinct().annotate(Count('product_name'))

在models.py中

class product(models.Model):
    product_category=models.CharField(null=True,max_length=5000)
    product_category_id=models.CharField(null=True,max_length=5000)
    branch=models.CharField(default='',max_length=100)
    products=models.CharField(null=True,max_length=5000)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(default=timezone.now)
   
    def __str__(self):
     return '{},{}'.format(self.products, self.product_category)

class enquiry(models.Model):
    comment=models.CharField(default='',max_length=100,null=False)
    branch=models.CharField(default='',max_length=100)
    created_at = models.DateField(auto_now_add=True)
    updated_at = models.DateTimeField(default=timezone.now)
    created_by=models.CharField(default='',max_length=100)
    status=models.CharField(default='',max_length=100)
    commentupdate=models.CharField(default='',max_length=100)
    product=models.ForeignKey(product,models.CASCADE,default='')
    product_name=models.CharField(default='',max_length=100)
    product_category=models.CharField(default='',max_length=100)
    type=(
        ('Walkin','Walkin'),
        ('Activity','Activity'),
        ('TeleEnq','TeleEnq'),
        ('Digital','Digital'),
        )
    type=models.CharField(choices=type, default='',max_length=100)
    status_type=(
        ('Retail','Retail'),
        ('Closed','Closed'),
        )
    status_update=models.CharField(choices=status_type, default='open',max_length=100)

在html中

  {%for pr in act%} 
  <tr>
  <td>{{forloop.counter}}</td>
  <td>{{pr.product_name}}</td>               
  <td>{{pr.product_name__count}}</td>
  {%endfor%}

  {%for pr in wal%}
  <td>{{pr.product_name__count}}</td>
  {%endfor%} 

  {%for pr in tele%}
  <td>{{pr.product_name__count}}</td>
  {%endfor%} 

  {%for pr in digital%}
  <td>{{pr.product_name__count}}</td>
  {%endfor%} 
  </tr>

我想要这样的输出:

product walkin Activity Tele DIgital Total
p1 4 1 3 0 8
p2 0 6 0 1 7
p3 2 1 3 0 6
p4 3 2 0 4 9
:------: :------: :-------: :----: :-------: :-----:
total 9 10 6 5 30

【问题讨论】:

    标签: python django filter jinja2


    【解决方案1】:

    使用注解和aggregation

    我认为,通过阅读该文档,您会使用查询集

    qs = Product.objects.all.annotate(
           walkin_count=Count('enquiry', filter=Q( enquiry__type='Walkin' ))
        ).annotate(
           activity_count=Count('enquiry', filter=Q( enquiry__type='Activity' ))
        ).annotate ...
    

    注释将字段添加到检索到的对象中,因此在您的模板中

    {% for prod in products %}
        <tr>
          <td>{{prod}}</td>
          <td>{{prod.walkin_count}} </td>
          <td>{{prod.activity_count}} </td>
          ...
        </tr>
    

    总数的最后一行,我不确定你是否可以以任何方式将它们添加到同一个查询集中,但从查询集中计算它们很容易:

    total_walkins = sum( [ prod.walkin_count for prod in qs ] )
    

    并将这些在上下文中传递给您的模板。

    顺便说一句,它是一个 Django/Python 约定,即(模型)类以大写字母开头。试图将product 解释为模型而不是实例,这让我很困惑。我的回答可能出于习惯而大写。

    【讨论】:

    • 非常感谢您理解我的问题它有效:)
    【解决方案2】:

    首先,我对你的风格有一些基本的建议:

    1. 永远不要将type 用作字段/变量。例如,您可以将其命名为 _typetype_。使用内置函数的名称是一种非常糟糕的做法。
    2. 不要对模型多次使用相同的名称。它可能会覆盖自身并出现意外行为或给出错误(再次type)。更不用说这种方式可读性较差。
    3. 类的名称应该用 CamelCase 书写(enquiry - 不好,Enquiry - 更好)。
    4. 如果EnquiryProduct 中有ForeignKey,则不建议在Product 中也有具有相同值的字段。

    我建议您了解 Django 的模型关系(链接在底部)。现在,我会给你一些可能有用的提示。

    models.py:

    Enquiry(models.Model):
        ...
        product = product=models.ForeignKey(Product, related_name='enquires', on_delete=models.CASCADE, default='')
        ...
    

    然后您可以通过以下方式访问相关对象:

    an_enquiry = Enquiry.objects.get(id=1)
    an_enquiry.product   # accesses the related object
    an_enquiry.product.product_category   # returns the 'product_category' field value from related object
    

    如果需要,也可以轻松反转:

    a_product = Product.objects.get(id=1)
    all_queryset = a_product.enquires.all()   # returns all related objects in a QuerySet
    wal_queryset = a_product.enquires.filter(a_type='Walkin')   # returns filtered QuerySet
    wal_queryset.count()   # returns sum of objects in a queryset
    

    在你的模板中:

    {% for product in wal_queryset %}
        {{ product.wal_queryset.count }}
    {% endfor %}
    

    the Django docs 上了解它,因为它提供了很多机会。理解关系使 Django 成为非常强大的工具。

    【讨论】:

    • 感谢您的回复,我将改变我的编码风格:)
    猜你喜欢
    • 2021-09-28
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    相关资源
    最近更新 更多