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

时间:2015-11-24 19:39:14

标签: python html django postgresql django-queryset

与看起来似乎有点挣扎应该是一个简单的问题......

基本上我有一些网站会在几年内发生对象计数:

示例:

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中显示它。

这是我的MODELS.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'

这是我试图在VIEWS.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}]

但是 - 我希望它作为QuerySet(而不是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的所有值。

同样,我正在寻找的是LATEST year. Max(count), Max(year)的最高分数 - 我确信它会以某种方式播放......

谢谢!

3 个答案:

答案 0 :(得分:2)

如何按年份排序并计算并使用.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()指定视图中每个模型所需的值。结果 也可以在模板中迭代。

答案 1 :(得分:1)

编辑:

虽然以下答案对我有用,但我对表现感到担忧...... 所以我根据用户5219763进行了重新调整 - 现在更干净了......

我已经修好了,发现这个有用......

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 %}

谢谢,伙计们!

答案 2 :(得分:0)

QuerySetValuesQuerySet有两种解决方案。

<强> 1。查询集

不推荐用于大型SiteCounts表,因为性能 - 对于每个站点,您将获得另一个查询来获取Counts的最新对象(复杂度{{ 1}})。但如果行数很少,那就没问题了。例如:

视图

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()

这就是全部!

<强> 2。 ValuesQuerySet

您应该在<table> {% for x in dat %} <tr> <td>{{x.counts_latest.count|floatformat}}</td> <td>{{x.counts_latest.year}}</td> </tr> {%endfor%} </table> 列出所有values字段,这些字段可以在模板中使用。例如:

视图

Counts

模板

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

希望这有帮助!