当ManyToMany关系通过直通表获得额外数据时,如何获取模板中的数据?从视图中我可以获取数据,如果我提供参数:
class Category(models.Model):
title = models.CharField(max_length=1024,null=True,blank=True)
entry = models.ManyToManyField(Entry,null=True,blank=True,
related_name='category_entry',
through='CategoryEntry',
)
class CategoryEntry(models.Model):
category = models.ForeignKey(Category)
entry = models.ForeignKey(Entry)
votes = models.IntegerField(null=False, default=0)
def category_detail(request, pk):
category = models.Category.objects.select_related().get(pk=pk)
entries = category.entry.order_by('-temp_sort_order').filter(temp_sort_order__gte=0)
for entry in entries:
assert isinstance(entry, models.Entry)
ce = models.CategoryEntry.objects.get(entry=entry, category=category)
pprint('Show votes as a test: ' + ce.votes) #OK
pprint('entry title: ' + entry.title) #OK
pprint('entry votes: ' + str(entry.category_entry.votes)) #BAD
pprint('entry votes: ' + str(entry.entry.votes)) #BAD
....
但模板无法为方法提供参数。
https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships上的文档对模板没有提及。使用for entry in category.category_entry_set.all
使用'Category'对象没有属性'category_entry_set'。 category.category_entry.all
也不起作用。
最终我想在模板中显示额外的数据:
{% for entry in entries %}
<ul>
<li>Title: {{ entry.title }} Votes: {{ entry.category_entry.votes }} {{ entry.entry.votes }}</li>
</ul>
{% endfor %}
答案 0 :(得分:1)
更新我的答案,我错误地将相关经理放在错误的模型上,在你的情况下,就像安德烈所说,从类别中获取条目的正确方法是:
category.entry.all()
现在,解决您的迭代和订购问题。在python中它看起来像这样:
for ce in category.categoryentry_set.order_by('-votes'):
print ce.entry, ce.votes
这将为您提供按投票排序的每个类别的条目。要将此模板转换为模板,您只需将查询集category.categoryentry_set.order_by('-votes')
保存到变量中并对其进行迭代即可。
答案 1 :(得分:1)
如果模板中有类别实例:
category.entry.all -> list of entries
如果模板中有一个条目实例:
entry.category_entry.all -> list of categories
您应该以复数形式呼叫M2M字段, 那么你将有一个更易读的代码
category.entries.all
%model%_set语法(或相关名称,如果已指定)用于通过向后关系访问模型。
https://docs.djangoproject.com/en/1.4/topics/db/queries/#following-relationships-backward
但是如何获得与m2m实例关联的“投票”? - 布莱斯
我建议您采用以下方式:
class Category(models.Model):
title = models.CharField(max_length=1024,null=True,blank=True)
entries = models.ManyToManyField(Entry,null=True,blank=True,
related_name='categories',
through='CategoryEntry',
)
class CategoryEntry(models.Model):
category = models.ForeignKey(Category, related_name='category_entries')
entry = models.ForeignKey(Entry)
votes = models.IntegerField(null=False, default=0)
def category_detail(request, pk):
category = models.Category.objects.select_related().get(pk=pk)
category_entries = category.category_entries.filter(entry__temp_sort_order__gte=0).order_by('-entry__temp_sort_order')
for category_entry in category_entries:
# category_entry is an instance of the model CategoryEntry
pprint('category entry votes: ' + str(category_entry.votes))
pprint('entry title: ' + category_entry.entry.title)
....
HOW TO
entry = Entry.objects.get(pk=1)
entry.categories.all() # list of categories (here we work through related name of the field entries)
category = Category.objects.get(pk=1)
category.entries.all() # list of entries (here we work through m2m field entries)
category.category_entries.all() # list of CategoryEntry objects (through related name category_entries of the field category in model CategoryEntry)
答案 2 :(得分:0)
这是一个丑陋丑陋的黑客行事。过滤和排序后,处理列表并附加额外的模型字段。模板现在可以轻松访问:
entries = category.entry.order_by('-temp_sort_order').filter(temp_sort_order__gte=0)
for entry in entries:
assert isinstance(entry, models.Entry)
ce = models.CategoryEntry.objects.get(entry=entry, category=category)
entry.xxx_votes = mark_safe(ce.votes) # use {{ entry.xxx_votes to access }}
entry.xxx_ce = ce # Use {{ entry.ce.votes to access }}
return render_to_response('category.html')
希望有人可以提供更好的答案,或建议改进django本身。此解决方案不允许我对category.entry.order_by('-category_entry.votes')