在 django 中使用注释引用相关对象


有点

挣扎,似乎应该是一个简单的问题......

从本质上讲,我有一些网站在几年内发生了物体计数:

例:

site_id = Site1: (Year:2012,Count:133), (Year:2011, Count:150), (Year:2010, Count :110)
site_id = Site2: (Year:2010, Count:300), (Year:2010, Count 333)

数据在时间上是不连贯的(不是常规的 - 有些网站被计算了几年......其他网站没有......(..此外,有时这些地方每年被计算几次

我想

做的是获取每个站点的最新计数,如果有多个计数,我想获得最高计数。然后我想在HTML中显示它。

这是我的模型。.PY

class Counts(models.Model):
    count_id = models.AutoField(primary_key=True)
    site = models.ForeignKey('Site', blank=True, null=True)
    year = models.IntegerField(blank=True, null=True)
    count = models.FloatField(blank=True, null=True)
    class Meta:
        db_table = 'counts'

class Site(models.Model):
    site_id = models.TextField(primary_key=True)
    site_code = models.TextField(blank=True, null=True)
    site_name = models.TextField(blank=True, null=True)
    class Meta:
        db_table = 'site'

这是我尝试在视图中使用的查询。.PY

p = ['Site1','Site2']  ## Just for reference for the example... values come from a POST or a GET
A = Site.objects.filter(site_id__in = p).annotate(latest=Max('counts__year'))
context = RequestContext(request, {'dat':A})
template = loader.get_template('styles/searchResults.html')        
return HttpResponse(template.render(context))

以上只给了我最近几年:

[{'site_id': u'Site1','latest': 2012}, {'site_id': u'Site2','latest': 2010}]

我想要的是:

[{'site_id': u'Site1','latest': 2012,'count':133}, {'site_id': u'Site2','latest': 2010,'count':333}]

但是 - 我希望它作为查询集(而不是 ValuesQuerySet(,因为我想在我的 HTML 模板中引用它,如下所示:

<table>
{% for x in dat %}
    <tr><td>{{x.count|floatformat}}</td><td>{{x.year}}</tr>
{%endfor%}
</table>

我已经尝试了以下内容(从上面创建 A 后(: B = Counts.objects.filter(year__in = A.values('latest'(,site__site_id__in = p(.annotate(site_code=Max('site__site_id'((

但这基本上导致:

[{'site_id': u'Site1','latest': 2012,'count':133},{'site_id': u'Site1','latest': 2010,'count':110}, {'site_id': u'Site2','latest': 2010,'count':333},{'site_id': u'Site2','latest': 2010,'count':300}]

换句话说,它正在提取两个站点的 YEAR = 2010 或 2012 的所有值。

同样,我正在寻找的是最新year. Max(count), Max(year)的最高计数 - 我敢肯定以某种方式发挥作用......

谢谢!

按年份和计数排序并使用 .distinct(( 只获取每个站点的第一条记录怎么样?

A = Counts.objects.filter(site_id__in = p).order_by('site_id','-year','-count').distinct('site_id')

如果您需要相应的站点信息,可以在模板中访问

<table>
{% for x in dat %}
    <tr><td>{{x.count|floatformat}}</td><td>{{x.year}}</td><td>{{x.site.site_name}}</td></tr>
{%endfor%}
</table>

或者使用 .values(( 指定视图中每个模型所需的值。结果也可以在模板中迭代。

已编辑:

虽然下面的答案对我有用,但我担心性能......所以我根据 user5219763 重新散列 - 现在更干净了......

我捣鼓了一下,发现这很有效...

from itertools import chain
### First create an empty list to push querysets
qlist = []
### Iterate through each selected ID 
for x in p:
    ### Find the value for the latest year for each site id selected
    A = Site.objects.filter(site_id = x).aggregate(Max('counts__year'))['counts__year__max']
    if A:
        ### Find value of the highest count for year identified above for the selected site
        B = Counts.objects.filter(year = A, site__site_id=x).aggregate(Max('count'))['count__max']
        ### Now, resample the Site where the year is the max and count is max, then annotate the queryset
        ### with the values from year and count in the Counts table...
        C = Site.objects.filter(counts__year=A,counts__count=B).annotate(year = Max('counts__year'), count = Max('counts__count'))
        ### push this query to the list
        qlist.append(C)
    else:
        continue
            ### use itertools chain command to merge these into a single queryset
qs = list(chain.from_iterable(qlist))

现在我正在使用:

qs = Counts.objects.filter(site__site_id__in = p).order_by('site__site_id','-year','-count').distinct('site__site_id').select_related()

然后,在我的 HTML 中,我像这样引用它:

{% for x in dat %}
    <tr ><td>{{ x.site.site_name }}</td><td>{{x.site.site_code}}</td><td>{{x.count|floatformat}}</td><td>{{x.year}}</td></tr>
{% endfor %}

谢谢,伙计们!

QuerySetValuesQuerySet有两种解决方案。

1. 查询集

不建议用于大型Site表和Counts表,因为性能 - 对于每个站点,您将获得一个额外的查询来获取最新的Counts对象(复杂性O(N*M)(。但是,如果行数很少,那也没关系。例如:

视图

A = Site.objects.filter(site_id__in=p).annotate(latest=Max('counts_set__year'))
# Fetch latest Counts for each Site object
for site in A:
   site.counts_latest = site.counts_set.order_by('-year').first()

模板

<table>
{% for x in dat %}
    <tr>
        <td>{{x.counts_latest.count|floatformat}}</td>
        <td>{{x.counts_latest.year}}</td>
    </tr>
{%endfor%}
</table>

就这样!

2. 值查询集

您应该放入所有Counts字段的列表values这些字段可以在模板中使用。例如:

视图

A = Site.objects.values('counts_set__count', 'counts_set__year') 
        .filter(site_id__in=p).annotate(latest=Max('counts_set__year'))

模板

<table>
{% for x in dat %}
    <tr>
        <td>{{x.counts_set__count|floatformat}}</td>
        <td>{{x.counts_set__year}}</td>
    </tr>
{%endfor%}
</table>

希望这有帮助!

最新更新