2

当多对多关系通过直通表有额外数据时,如何获取模板中的数据?从一个视图中,如果我提供参数,我可以获得数据:

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上的文档对模板保持沉默。使用 usingfor 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 %}
4

3 回答 3

2

如果您在模板中有一个类别实例:

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)
于 2012-07-16T07:37:45.920 回答
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')到变量中并对其进行迭代。

于 2012-07-14T00:37:20.530 回答
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')

于 2012-07-16T19:48:10.383 回答