tags:

views:

211

answers:

5

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" page 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?

A: 

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.

Roberto Liffredo
A: 

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())
ozan
I don't know if this is the "best" solution to the problem, but it's doing the trick for me right now, and I can understand it. :)
Trey Piepmeier
+1  A: 

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 %}
Ben James
A: 

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))
Clash
+1  A: 

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.

Trey Piepmeier