【问题标题】:Filtering a reverse lookup in Django template在 Django 模板中过滤反向查找
【发布时间】:2021-01-05 15:37:10
【问题描述】:

我有一个看起来像这样的模型

class Invoice(models.Model):
    inv_number = models.CharField(max_length=10, primary_key=True)
    customer = models.ForeignKey(Customer, on_delete=models.PROTECT)
    inv_date = models.DateField()

class Txn(models.Model): 
    invoice = models.ForeignKey(Invoice, on_delete=models.PROTECT)
    transaction_date = models.DateField()
    reference = models.CharField(max_length=12)
    amt = models.IntegerField()

我想在我的模板中显示一份报告,其中列出了过滤后的发票,每个发票都有一个过滤交易的子列表。

在我看来,我做了以下事情:

invoice_list = Invoice.objects.filter(customer=customer)

我传入我的模板。在模板中,我执行以下操作:

{% for invoice in invoice_list %}
   {{ invoice.inv_number }}, {{ invoice.customer}}, {{ invoice.inv_date }}
   {% for txn in invoice.txn_set.all %}
      {{ txn.transaction_date }}, {{ txn.reference }}, {{ txn.amt }}
   {% endfor %}
{% endfor %}

这非常适合显示每个已过滤发票的整个交易列表。问题是,如何过滤模板中每张发票的交易列表 - 如果我只想要某个日期范围内的交易或与特定参考匹配的交易怎么办?有没有办法在将主查询集放入上下文之前将过滤器传递给视图中每个发票的 txn_set 查询集,而不将它们转换为列表?

感谢您的回复!

【问题讨论】:

    标签: python django django-views django-templates django-queryset


    【解决方案1】:

    建议:在视图中收集发票和交易,而不是在模板中。

    使用此视图代码,您可以将查询数量减少到 1,因此它比您的代码优化得多(查询每个发票的 Txn 表):

    # build basic query
    qs = Txn.objects.select_related('invoice')\
        .filter(invoice__customer=customer)\
        .order_by('transaction_date')
    
    # add filtering; here is an example, but it could be with date filter as well
    reference = request.GET.get('reference', '')
    if len(reference) > 0:
        qs = qs.filter(reference__icontains=reference)
    
    invoice_dict = {}
    for txn in qs:
        # add the Invoice if it does not exist yet
        if txn.invoice_id not in invoice_dict:
            invoice_dict[txn.invoice_id] = {
                'invoice': txn.invoice,
                'txn_list': [],
            }
    
        # add the Txn
        invoice_dict[txn.invoice_id]['txn_list'].append(txn)
    
    # sort by Invoice date
    invoice_data_list = sorted(
        invoice_dict.values(),
        key=lambda x: x['invoice'].inv_date)
    

    然后在你的模板中:

    {% for elem in invoice_data_list %}
        {{ elem.invoice.inv_number }}
        {{ elem.invoice.customer}}
        {{ elem.invoice.inv_date }}
    
        {% for txn in elem.txn_list %}
             {{ txn.transaction_date }}
             {{ txn.reference }}
             {{ txn.amt }}
        {% endfor %}
    {% endfor %}
    

    【讨论】:

    • 这非常有效,而且效率更高。谢谢!
    猜你喜欢
    • 2013-08-18
    • 1970-01-01
    • 2013-08-23
    • 2015-09-13
    • 2015-08-18
    • 2011-05-09
    • 2018-05-07
    • 1970-01-01
    • 2023-04-11
    相关资源
    最近更新 更多