【问题标题】:Get a QuerySet of Months and the amount of expense获取月份的查询集和费用金额
【发布时间】:2014-11-24 12:32:31
【问题描述】:

这看起来像一个简单的问题,但我无法获得预期的结果。我有一张这样的桌子:

| id# | Concept | Amount |    Date    |
| ... |   ...   |   10   | 10/12/2013 |
| ... |   ...   |   20   | 12/12/2013 |
| ... |   ...   |   30   | 02/01/2014 |
| ... |   ...   |   40   | 03/01/2014 |
| ... |   ...   |   50   | 04/02/2014 |
| ... |   ...   |   60   | 05/02/2014 |

我想找到一种方法来使用此表获取 QuerySet:

| Date.year | Amount |
|    2013   |    30  |
|    2014   |   180  |

我想我可以通过类似的方式获得,例如:

| Date.month | Amount |
|   12/2013  |    30  |
|   01/2014  |    70  |
|   02/2014  |   110  |

有什么想法吗?

编辑

我会尽力澄清,对于任何误解或不好的解释,我深表歉意:-/

我有这个模型:

from django.db import models
from django.core.urlresolvers import reverse

class Expense(models.Model):
    concept = models.CharField(max_length=255)
    date = models.DateField()
    amount = models.DecimalField(max_digits=7,decimal_places=2)

    class Meta:
        ordering = ['date']

    def __unicode__(self):
        return '%s' % (self.concept)

    def get_absolute_url(self):

我有这个模板:

...
<table>
  {% for year in years %}
    <tr>
      <td width="40%">
        {{ year.year }}
      </td>
      <td width="60%" align="right">{{ year.total_amount }}</td>
    </tr>
  {% endfor %}    
</table>
...

我正在尝试为我的view 找到一个查询集:

def index(request):
    years = Expense.objects.values('date').annotate(total_amount=Sum('amount'))
    return render(request, 'account/index.html', {'years': years})

在这种情况下,years 正在返回与我想要的“接近”的东西,因为它按日期对 expenses 进行分组,但我想按月或年对它们进行分组,而不是按“日”分组。

我不知道最好的方法是什么,查询费用或在模板中,或其他方式。这就是我需要的。我希望现在更清楚一点。

【问题讨论】:

  • Django 使用 ORM,你不能自己执行 SQL 命令。您需要有一个模型,该模型的字段映射到数据库中表的字段(理想情况下,您让 django 基于这些模型创建数据库)。然后,您可以使用模型并将行作为对象获取。那么你在这里遇到什么麻烦?配置模型或获取它们还是什么?你学过 Django 教程吗?
  • 我有模型“费用”及其属性,它看起来像第一个表。我可以按天(日期)对它进行排序:years = Expense.objects.values('date').annotate(total_amount=Sum('amount'));但不是在view 上按月份或年份(在template 上显示)
  • @AKX 是的,我见过这个,但它与我的情况有点不同。我不知道我怎样才能适应我的。 PO 有一个 GroupItems,其中有一个日期。所以他有点转发。我试图根据我的情况调整解决方案,但在尝试时遇到了一些错误:(
  • 假设你的模型是MyModelMyModel.objects.all().extra(select={'year': "EXTRACT(year FROM date)"}).values('year').annotate(amount=Sum('amount')) 不就行了吗?

标签: python sql django date group-by


【解决方案1】:

这种方法并不完全有效(因为您正在处理 python 端的数据),但这并不是说它无论如何都很慢。在大多数情况下,它应该可以无缝工作。

 #view
 def myview(request):
     expenses = Expense.objects.all().order_by('date')
     data = {}

     for exp in expenses:
         y = exp.date.strftime("%Y")
         if (data.has_key(y)):
             data[y].append(exp)
         else:
             data[y] = [exp]

     return render_to_response(request, "index.html", {"data": data})


 #html
 {% for year, expenses in data.items %}
   <h1> {{ year }} </h1>
   <ul>
     {% for expense in expenses %}
         <li><b>{{ expense.date|date:"M" }}:</b> {{ expense.amount }}</li>
     {% endfor %}
   </ul>
 {% endfor %}

你显然可以随心所欲地适应它。这个想法很简单——解析数据并在通过 SQL 获取数据后用 python 排列它。

【讨论】:

  • 好的,但这不是我想要的。我的意思是,我试图找到在模板中显示一年(2014 年)和当年总费用的最佳方式。我试图在模板中这样做,但是阅读 StackOverflow(以及我的常识:P)我发现这可能是一个不好的做法。所以我试图找到一个query 来获得一个具有这些值的“table”。
  • @makeMonday 哦,好吧,我现在明白你要做什么了。在我更新我的答案之前 - 效率对你来说是一个大问题吗?
  • @makeMonday 那里。更新了我的答案
  • [更正]:对不起@yuvi,我没看错。这仍然不是我想要的:(我会在我的解决方案中发布一个答案。也许它会更清楚我的问题。谢谢。
  • @makeMonday 你想先总结一下每年的结果吗?
【解决方案2】:

我终于能够得到预期的结果,但我不是很喜欢它。我仍然想知道是否有办法以类似于我所问的方式来解决这个问题。

基本上,我创建了另一个字典 (amounts),它在 expense 中查找年份,并在此基础上不断添加基于年份的 expense.amount。所以最后amounts 会是这样的:{2013: Decimal('16.58'), 2014: Decimal('104.66')}

我的解决方案:

views.py:

from django.template.defaulttags import register
...         
@register.filter
def get_item(dictionary, key):
    return dictionary.get(key)

def index(request):
    years = Expense.objects.dates('date','year')
    expenses = Expense.objects.all().values()
    amounts = {}

    for expense in expenses:
        year = expense['date'].year
        if year in amounts:
            amounts[year] = amounts[year] + expense['amount']
        else:
            amounts[year] = expense['amount']

    return render(request, 'index.html', {'years': years, 'amounts': amounts})

template:

<tbody> 
  {% for year in years %}
    <tr>
      <td width="50%">
        <a href="{{year.year}}">
          {{ year.year }}
        </a>
      </td>
      <td width="50%" align="right">{% if year.year in amounts %} {{ amounts|get_item:year.year }} {% endif %}</td>
    </tr>
  {% endfor %}
</tbody>

有更好的主意吗? ;)

【讨论】:

  • 你为什么不喜欢它?
  • 不是我不喜欢,只是我认为可能有一种更简单的方法,而不是创建一个字典来汇总金额,然后传递它等等。
猜你喜欢
  • 1970-01-01
  • 2013-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多