2009-08-16 79 views
2

我有一个模型书可以添加到用户的收藏夹。所以我定义的2类:Django模板用户请求


class Book(models.Model): 
    name = models.CharField(max_length = 40) 

class UserFavorite(models.Model): 
    book = models.ForeignKey(Book) 
    user = models.ForeignKey(User) 

现在我想显示在主菜单页的畅销书带图标或者“添加到收藏夹”或“从收藏夹中删除”。基本上,我将流行的书籍数组传递给一个模板,并从模板中循环这个数组,并应该说“如果book.is_in_favorites(request.user):...”,但这不可能从模板中获得。

回答

3

对此的最常见方法是装饰视图中的书籍对象。在视图代码,遍历所有的书籍,增加布尔值,指示他们是否是当前用户的喜爱与否:

for b in books: 
    b.is_fav = b.is_in_favorites(request.user) 

然后在模板:

{% for b in books %} 
    blah blah {{b.blah}} 
    {% if b.is_fav %}FAVORITE INDICATOR{% endif %} 
{% endfor %} 

如果你不这样做像修改书的对象,你可以与他们的注释包扎书籍类型的字典列表:

book_info = [{'book':b, 'is_fav':b.is_in_favorites(request.user)} for b in books] 

,并在你的模板中使用它:

{% for bi in book_info %} 
    blah blah {{b.book.blah}} 
    {% if bi.is_fav %}FAVORITE INDICATOR{% endif %} 
{% endfor %} 
+0

1)我必须在Book模型中定义is_fav吗?或者这会添加一个“即时”字段? 2)方法很好,虽然它需要运行许多选择语句(一个用于所有书籍,然后每个书籍用于is_fav),这会影响性能。可能有什么办法做到这一点,只有一个查询获取所有的书籍? – Vitaly 2009-08-16 18:45:40

+0

事实上,我发现有“额外”的条款,可以动态地添加属性,我会尽量利用它 – Vitaly 2009-08-16 18:55:55

+0

如果你想避免for语句引起的重复查找(并且因为select_related *不会*在这里帮助)您可以调用UserFavorites.objects.filter(user = request.user),并将您的书籍迭代与返回的UserFavorites集合进行比较。然后它只有2个数据库点击。 – 2009-08-16 18:57:20

1

我不明白这与模板有什么关系。你只需要显示一个链接到一个视图,该视图将book id作为参数,从请求中获取用户,并使用这两个用户添加UserFavourite。

编辑后更新:好的,我现在明白你的问题了。那么,正如你发现的那样,这种事情太复杂了,无法放入模板逻辑。它确实需要在您的视图或模板标签中进行。可能模板标签是最好的,因为您无疑会希望在多个视图/模板中使用此功能。

您可能会想要使用包含标签,因为它具有可以自动获取上下文的好处。喜欢的东西(未经测试):

@register.inclusion_tag('add_to_favourites.html', takes_context=True) 
def favourite_links(context): 
    user = context['request'].user 
    books = Book.objects.exclude(userfavourite__in=user) 
    return {'books': books, 'user':user} 

现在你只需要这使得使用通过上述标签返回书籍值的列表中选择模板片段。在您的主要模板中,只需使用favourite_links即可显示书籍链接。

+0

基本上,我将一系列流行书籍从主视图传递到模板。现在从模板我循环这个数组,并应该说像“如果book.is_in_favorites(request.user)” - 这是不可能的这样的smthth。我现在不在乎如何实现将本书添加到收藏夹的视图。 – Vitaly 2009-08-16 18:27:11