在 Django 模板中过滤反向查找

Posted

技术标签:

【中文标题】在 Django 模板中过滤反向查找【英文标题】:Filtering a reverse lookup in Django template 【发布时间】: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 查询集,而不将它们转换为列表?

感谢您的回复!

【问题讨论】:

【参考方案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 %

【讨论】:

这非常有效,而且效率更高。谢谢!

以上是关于在 Django 模板中过滤反向查找的主要内容,如果未能解决你的问题,请参考以下文章

04_Django-模板变量/标签/过滤器/继承-url反向解析

04_Django-模板变量/标签/过滤器/继承-url反向解析

django第三课 模板变量及过滤器

django的模板系统

DJANGO之自定义模板过滤器

Django 模板中 变量 过滤器 标签 的使用方法