从django queryset中的单个字段派生多个值

时间:2013-03-10 20:11:46

标签: django django-queryset

我的模型看起来有点像这样:

class InvoiceEntry(models.Model):
    ...
    username = models.CharField(max_length=20)  <-- the users name
    billtime = models.DecimalField()            <-- how much time has been spent
    billable = models.CharField(max_length=1)   <-- is this work billable? (Y or N)
...

这些字段无法更改 - 它们是已包含200k +行的表的一部分。

我需要创建一个返回的查询集:

  • 用户名
  • 可结算时间(每位用户)的总和
  • 不可计算时间(每位用户)的总和

...说,过去7天(这很容易)。

最好的方法是什么?

提前致谢 - 帕特里克

1 个答案:

答案 0 :(得分:2)

如果将billable设置为BooleanFIeld(参见:https://docs.djangoproject.com/en/dev/ref/models/fields/#booleanfield),那将会更容易(并且对你们更好)。对于CharField,默认表单是textinput框,对于bool字段,它是一个复选标记 - 对用户更有意义!而不是向人们解释他们必须使用Y或N.

此外,您的模型没有主键。您将来可能需要为每个用户视图定义。 userid = models.AutoField(primary_key=True)可以为您节省大笔麻烦。

如果你有一个主键,你可以避免将来与重复的用户名混淆。例如,我的解决方案将john.smith计为一个用户,如果有两个不同的用户具有相同的名称(您的Model目前允许这样做,除非您添加unique = True)。

例如。

   class InvoiceEntry(models.Model):
        username = models.CharField(max_length=20)  <-- the users name
        billtime = models.DecimalField()            <-- how much time has been spent
        billable = models.BooleanField()   # Now you just use consistent True or False

就个人而言,对于像这样的任务,我只生成自己的字典。使用原始模型。

q = InvoiceEntry.objects.all() # only call it once
results = []
users = q.values_list('username',flat=True)
for user in users
    dict = { 
        "user": user,
        "unbillable":sum(q.filter(username = user,billable="N").values_list('billtime',flat=True)),
        "billable":sum(q.filter(username = user,billable="Y").values_list('billable',flat=True)),
        }
    results.append(dict)

我建议将字段更改为布尔值:

q = InvoiceEntry.objects.all() # only call it once
results = []
users = q.values_list('username',flat=True)
for user in users
    dict = { 
        "user": user,
        "unbillable":sum(q.filter(username = user,billable=False).values_list('billtime',flat=True)),
        "billable":sum(q.filter(username = user,billable=True).values_list('billtime',flat=True)),
        }
    results.append(dict)

现在,如果你在视图中使用了render_to_reponse,那么你的模板会是这样的:

{% for result in results %}
{{ result.user }}
{{ result.unbillable }} 
{{ result.billable }}
{% endfor %}