2014-06-28 67 views
0

我試圖根據名稱過濾成員並返回成員和關聯公司。我的模型是:如何在django中使用外鍵上的過濾器「group by」

class Member(models.Model): 
    first_name = models.CharField(max_length=40, blank=False, null=False) 
    last_name = models.CharField(max_length=40, blank=False, null=False) 

class Affiliation(models.Model): 

    member = models.ForeignKey(Member) 
    company = models.ForeignKey(Company) 
    date_entered = models.DateField(null = False, blank = False) 
    date_exited = models.DateField(null = True, blank = True) 

class Company(models.Model): 
    name = models.CharField(max_length = 100) 

,然後我想在成員搜索,發現每個人的名字某些字符串相匹配,並告訴他們都擁有各自公司的隸屬關係一起。因此,對於搜索我可以這樣做:

def member_search(request): 

    member_list = Member.objects.filter(
       Q(first_name__icontains=request.POST['q'].lower()) | 
       Q(last_name__icontains=request.POST['q'].lower())) 

    return render_to_response('member/member_list.html', {'member_list': member_list }) 

def member_search2(request): 

    affiliation_list = Affiliation.objects.filter(
       Q(member__first_name__icontains=request.POST['q'].lower()) | 
       Q(member__last_name__icontains=request.POST['q'].lower())) 

    return render_to_response('member/member_list2.html', {'affiliation_list': affiliation_list }) 

在第一種情況下,模板會是這樣的:

<ul> 
    {% for member in member_list %} 
     <li> 
      <a href="/member/{{ member.pk }}">view</a> 

      <a href="/member/{{ member.pk }}/update">edit</a> 

      {{ member.first_name }} {{ member.last_name }} 

      {{ member.affiliation.all ??? }} 

     </li> 
    {% endfor %} 
</ul> 

,但我看不出如何扭轉回通過Affiliation ForeignKey。我懷疑我的過濾器將不得不改變,但我不明白如何。

,並在第二種情況下它會是這樣的:

<ul> 
    {% for affiliation in affiliation_list %} 
     <li> 
      <a href="/member/{{ affiliation.member.pk }}">view</a> 

      <a href="/member/{{ affiliation.member.pk }}/update">edit</a> 

      {{ affiliation.member.first_name }} {{ affiliation.member.last_name }} 

      {{ affiliation.member.company.name }} 

     </li> 
    {% endfor %} 

但後來我得到多行的成員,如果它們與多個公司下屬。我看了一下彙總,但在這種情況下並不清楚,因爲我也想列出這些公司。

我想要的到底是什麼:

member 1 (company 1 [entry date], company 2 [entry date]) 
member 2 (company 1 [entry date]) 
member 3 (company 2 [entry date]) 

這是非常有可能的另一個問題重複,但我還沒有發現這個問題:-)。這似乎是人們想要做的常見事情。

+0

想一想更多我想我傾向於第二種方法,因爲我真的很想有'會員1(公司1 [入會日期])等等 – brechmos

回答

2

這裏是你可以嘗試什麼:

爲1,你可以得到的隸屬關係與affiliation_set

{{ member.affiliation_set.all }} 

對於第二,你需要得到你想顯示值的字典。之後,您可以使用regroup模板過濾器標籤將dict合適地分組。示例代碼

def member_search2(request): 

    affiliation_list = Affiliation.objects.filter(#your filter ...) 
         .values('member__first_name', 'member__last_name', 
           'company__name', `date_entered') 
     .... 

而且在模板

{% regroup affiliation_list|dictsort:"member__first_name" by 
     member__first_name as aflist %} 

<ul> 
{% for af in aflist %} 
    <li> {{af.grouper }} 
    <ul> 
    {%for m in af.list %} 
     <li> {{m.company__name}} : {{m.date_entered}} </li> 
    {%endfor%} 
    </ul> 
    </li> 
{%endfor%} 
</ul> 
+0

作爲一邊,我將如何排序姓氏,FIRST_NAME? – brechmos

+0

讓我重新說明我的問題......我想按member_id分組,因爲人們可能會有相同的名稱,我想按姓氏排序,名字。我嘗試了{%regroup affiliation_list | dictsort:「member__last_name」by member__id as aflist%}',但是會員ID在{{af.grouper}}'中列出。那麼我怎麼會把他們的名字放在那裏,然後按'member__last_name,member__first_name'排序呢? – brechmos

1

第一種方法是迄今爲止簡單,而且還可以讓你所需輸出 - 如羅漢顯示,您只需要使用{{ member.affiliation_set.all }}每個成員。

但是,這將是非常昂貴的,因爲每個調用都是另一個數據庫查詢,並且從聯屬到公司的跳轉每次都是另一個數據庫調用。您可以通過在初始數據庫調用使用prefetch_related使這個便宜了不少:

member_list = Member.objects.prefetch_related('affiliation__toppings').filter(...) 

另一件事想,雖然它不會與您當前的場景一定幫助,是會員和公司之間的關係是實際上是多對多,並且具有作爲直通表的附屬關係。您可以在不通過聲明明確地改變你的數據庫結構添加額外的功能:

class Member(models.Model): 
    ... 
    companies = models.ManyToManyField('Company', through='Affiliation') 

,現在成員對象可以做member.companies.all()直接獲得他們的所有公司。

+0

感謝您的幫助。讚賞。 – brechmos

+0

這最後一件事是合乎邏輯的改變,對嗎? (因此關於不改變數據庫結構的評論?)它實際上會非常有幫助。 – brechmos

+0

是的。 –