2015-11-24 81 views
2

想找點什麼好像它應該是一個簡單的問題鬥爭的相關對象與註釋...參考在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中顯示。

這裏是我的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使用

​​

查詢以上給了我只有最近幾年:

[{'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> 

我曾嘗試以下(創建從上面後): B = Counts.objects.filter(year__in = A.values( '最近的'),site__site_id__in = p)的.annotate(site_code =最大( '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)最高計數 - 我敢肯定,在某種程度上扮演......

謝謝!

回答

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()指定從視圖中的每個模型需要的值。 的結果也是也可以在模板中迭代。

+0

感謝你 - 實際上非常接近我需要的 - 這大部分返回我所需要的。我只需要更進一步,從site_name和site_code(從站點模型) – GrantRWHumphries

+0

中將.select_related()添加到上述結果中,每個count對象都有相應的站點對象作爲屬性,site_name和site_code可通過模板中的內容獲得。所以A [0] .site.site_name會返回站點名稱。 select_related停止需要額外的數據庫命中,但該網站已經可用無論如何 – user5219763

+0

這很好,謝謝user5219763 – GrantRWHumphries

0

有兩種解決方案QuerySetValuesQuerySet

1.查詢集

不建議用於大型SiteCounts表,因爲性能 - 每一個網站,你會得到一個額外的查詢來獲取的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. ValuesQuerySet

你應該把所有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> 

希望這有助於!

+0

嗨阿爾貝 - 感謝您的建議。然而。您提供的ValuesQuerySet代碼每年都會列出。 「[{'counts__year':無,'counts__count':無,'latest':無},{'counts__year':1994,'counts__count':807.0,'latest':1994}等等。創建一個ValuesQuerySet,它不能像你在模板中描述的那樣遍歷。QuerySets可以工作,但是ValuesQuerySets沒有那麼多。 – GrantRWHumphries

1

編輯:

雖然下面的答案爲我工作,我很關心性能... 所以我基於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 %} 

謝謝你,夥計!

+0

答:好。答案中的其他問題 - 這些不太可能被看到或迴應,因爲這不是在這裏工作的方式。如果您有新問題,請點擊[問問題](// stackoverflow.com/questions/ask)按鈕。 – Mogsdad