【问题标题】:ValueError: too many values to unpack (expected 2) in Django Window functionValueError:在 Django Window 函数中解包的值太多(预期为 2)
【发布时间】:2021-04-18 11:19:30
【问题描述】:

我希望我的数据显示如下:

Date              installment month      amount      total
January 1, 2021   January                30000       30000
February 1, 2021  February               40000       70000 (i.e sum of 30000 and 40000)
March 1, 2021     March                  30000       100000 (i.e sum of 30000, 40000 and 30000)
.
.
and so on..

为此,我在我的 InstallmentListView 中使用了 aggregate(),如下所示:

views.py

class InstallmentListView(ListView):
    model = Installment
    template_name = 'client_management_system/installment_detail.html'
    context_object_name = 'installments'

    # This function is to show the installments of the client, the details of which we are seeing currently, and
    # pk=self.kwargs['pk'] is to get the client id/pk from URL
    def get_queryset(self):
        user = get_object_or_404(Client, pk=self.kwargs['pk'])
        return Installment.objects.filter(client=user)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        user = get_object_or_404(Client, pk=self.kwargs['pk'])
        queryset = Installment.objects.annotate(total=Window(expression=Sum('installment_amount'), order_by=F('installment_month').asc(), frame=RowRange(end=0)))
        context['total'] = queryset
        @register.filter
        def get_item(total, key):
            return total.get(key)
        return context`

我的模板文件如下:

模板.html

<!DOCTYPE html>
{% extends "client_management_system/base.html" %}
{% block content %}
<body>
  <legend class="border-bottom mb-4"><h5>Installment History</h5></legend>
  <article class="media content-section">
    <div>
      <table id="installmentTable" style="width:100%">
        <tr>
          <th style="width:150px">Date</th>
          <th style="width:250px">Installment Month</th>
          <th style="width:170px">Amount</th>
          <th style="width:100px">Balance</th>
        </tr>
        {% for installment in installments %}
        <fieldset>
          <tr>
            <td>{{ installment.installment_date|date:"F d, Y" }}</td>
            <td>{{ installment.installment_month }}</td>
            <td>{{ installment.installment_amount }}</td>
            <td>{{ total|get_item:'installment_amount__sum' }}</td>
          </tr>
        </fieldset>
        {% endfor %}
      </table>
    </div>
  </article>
</body>
{% endblock %}

但我收到以下错误:

ValueError: too many values to unpack (expected 2)

看来我没有正确实现 Window 功能。有谁知道如何解决这个问题?

【问题讨论】:

  • 聚合将是所有实例的总和...我相信我确实向您展示了如何使用Window 函数,这些函数将在您的previous question 中执行您想要的操作?你为什么不使用它?
  • 感谢您的回复。我确实尝试过,它给了我一个错误ValueError: too many values to unpack (expected 2)。我可以在下面的答案部分写下我的方法吗?以便您更好地了解我在做什么。
  • 答案不是用来提问的,你应该edit你的问题来澄清。
  • 我已经做到了。也许现在你可以得到一个清晰的画面。谢谢

标签: django django-models django-views django-templates


【解决方案1】:

你写过:

queryset = Installment.objects.annotate(total=Window(expression=Sum('installment_amount'), order_by=F('installment_month').asc(), frame=RowRange(end=0)))
context['total'] = queryset

如变量名queryset 所示,是一个查询集,即Installment 实例的集合。然而后来你写了total|get_item:'installment_amount__sum',它实际上转换为queryset.get('installment_amount__sum'),这没有意义,显然会给你一个错误。

相反,您想将此窗口表达式添加到 get_queryset 返回的查询集中,还想在 installment_date 上使用 order_by 对字符串月份进行排序不会使很有道理:

class InstallmentListView(ListView):
    model = Installment
    template_name = 'client_management_system/installment_detail.html'
    context_object_name = 'installments'

    # This function is to show the installments of the client, the details of which we are seeing currently, and
    # pk=self.kwargs['pk'] is to get the client id/pk from URL
    def get_queryset(self):
        user = get_object_or_404(Client, pk=self.kwargs['pk'])
        return Installment.objects.filter(client=user).annotate(
            total=Window(
                expression=Sum('installment_amount'),
                order_by=F('installment_date').asc(),
                frame=RowRange(end=0)
            )
        )
    
    # Remove your `get_context_data`

接下来在模板中你可以简单地写:

{% for installment in installments %}
    <fieldset>
        <tr>
            <td>{{ installment.installment_date|date:"F d, Y" }}</td>
            <td>{{ installment.installment_month }}</td>
            <td>{{ installment.installment_amount }}</td>
            <td>{{ installment.total }}</td>
        </tr>
    </fieldset>
{% endfor %}

注意:你为什么还要存储installment_month,你可以从installment_date得到它...另外,你的自定义模板标签是 不必要的,字典查找可以在模板中简单地完成 如{{ variable.key_name }}

【讨论】:

  • 实施了修改。它给出了以下错误:django.db.utils.NotSupportedError: This backend does not support window expressions.
  • @RazaJaved 您使用哪个版本的 Django 以及哪个数据库?如果 sqlite3 那么它是什么版本(运行import sqlite3print(sqlite3.sqlite_version) 来检查)?
  • 我使用的是 Django 版本 2.1.3,我使用的是 sqlite3 数据库,它的版本是 3.23.1
  • @RazaJaved Django 从 Django 版本 3.0 开始支持 sqlite3 中的窗口表达式,sqlite3 版本为 &gt;=3.25.0 如果您可以升级版本,这将起作用。
猜你喜欢
  • 1970-01-01
  • 2018-05-22
  • 2017-08-29
  • 1970-01-01
  • 2016-09-11
  • 1970-01-01
  • 2020-08-30
  • 2014-07-31
  • 2017-12-14
相关资源
最近更新 更多