开发者

Compare attributes of a Django Queryset in a template using the `in` Operator

I'm trying to use the in operator to determine if a template variable on the current page is also a foreign key in another model.

The model is like so:

class WishlistItem(models.Model):
    user  = models.ForeignKey(User, related_name='wishlist_items')
    issue = models.ForeignKey(Issue)

On the "Issue" 开发者_如何学JAVApage template, I'm trying to do this:

{% if issue in user.wishlist_items %}
{% else %}
    {# A button to add the issue to the user's wishlist #}
{% endif %}

What I need to do is to get at the issue attribute of the wishlist_items QuerySet for the currently logged-in user and compare it to the issue object of the current page. I'm at a loss for how to do this. Do I need to write a templatetag to do this?


I ended up solving this by writing a template filter:

@register.filter
def in_list(obj, arg):
    "Is the issue in the list?"
    return obj in (item.issue for item in arg)

Then I could do something like this in a template:

{% if issue|in_list:user.wishlist_items.all %}

I got the idea from the answer on this Stack Overflow question.


It seems that there's a relationship between User and wishlist issues that you ought to express as a ManyToManyField on the User. If there is extra metadata about the relationship that you need to record in a WishlistItem, then use through=WishlistItem.

If the User model is from the auth app, you'll need to extend the User model to achieve this (see this blog post for some help). For example:

class MyUser(User):
    wishlist_issues = models.ManyToManyField(Issue, through=WishlistItem)
    # ...

Then, in your template use:

{% if issue not in user.wishlist_issues %}
    {# A button to add the issue to the user's wishlist #}
{% endif %}


wishlist_items is not a queryset - it's a manager. wishlist_items.all IS a queryset, but obviously it is a queryset of WishlistItem objects, not Issue objects. What I would do is handle this logic in the view... something like:

user_has_issue = issue in (wl.issue for wl in request.user.wishlist_items.all())


If I understood correctly, instead of writing a templatetag for it you can pass that as a parameter of the view.

def myView(request):
    return render_to_response('template.html', 
            {'query': queryToCheckIfIssueInWishList}, 
            RequestContext(request))


I think what you are refering to should go into the view, more than the template.
Of course, you could create some templatetag, however Django's approach to templates is to maintain them as dumb as possible, and move all logic to the view.

On the other hand, moving the logic in the view, and then passing the additional information to the template should be quite straightforward, and I would definitely go for that solution.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜