我正在尝试根据名称过滤成员并返回成员和附属公司。我的模特是:
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 :(得分:2)
以下是您可以尝试的内容:
对于1st,您可以与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>
答案 1 :(得分:1)
第一种方法到目前为止更简单,仍然可以获得所需的输出 - 正如Rohan所示,您只需要为每个成员使用{{ member.affiliation_set.all }}
。
然而,这将是非常昂贵的,因为每个调用是另一个数据库查询,并且从关联到公司的跳跃每次都是另一个数据库调用。您可以在初始数据库调用中使用prefetch_related
来降低成本:
member_list = Member.objects.prefetch_related('affiliation__toppings').filter(...)
要考虑的另一件事是,虽然它对您当前的情况不一定有帮助,但会员和公司之间的关系实际上是多对多关系,Affiliation是直通表。您可以通过明确声明来添加额外的功能而无需更改数据库结构:
class Member( models.Model ):
...
companies = models.ManyToManyField('Company', through='Affiliation')
现在成员对象可以member.companies.all()
直接获取所有公司。