tags:

views:

266

answers:

1

I am using the standard User model (django.contrib.auth) which comes with Django. I have made some of my own models in a Django application and created a relationship between like this:

from django.db import models
from django.contrib.auth.models import User

class GroupMembership(models.Model):
    user = models.ForeignKey(User, null = True, blank = True, related_name='memberships')
    #other irrelevant fields removed from example

So I can now do this to get all of a user's current memberships:

user.memberships.all()

However, I want to be able to do a more complex query, like this:

user.memberships.all().select_related('group__name')

This works fine but I want to fetch this data in a template. It seems silly to try to put this sort of logic inside a template (and I can't seem to make it work anyway), so I want to create a better way of doing it. I could sub-class User, but that doesn't seem like a great solution - I may in future want to move my application into other Django sites, and presumably if there was any another application that sub-classed User I wouldn't be able to get it to work.

Is the best to create a method inside GroupMembership called something like get_by_user(user)? Would I be able to call this from a template?

I would appreciate any advice anybody can give on structuring this - sorry if this is a bit long/vague.

+3  A: 

First, calling select_related and passing arguments, doesn't do anything. It's a hint that cache should be populated.

You would never call select_related in a template, only a view function. And only when you knew you needed all those related objects for other processing.

"Is the best to create a method inside GroupMembership called something like get_by_user(user)?"

You have this. I'm not sure what's wrong with it.

 GroupMembership.objects.filter( user="someUser" )

"Would I be able to call this from a template?"

No. That's what view functions are for.

 groups = GroupMembership.objects.filter( user="someUser" )

Then you provide the groups object to the template for rendering.


Edit

This is one line of code; it doesn't seem that onerous a burden to include this in all your view functions.

If you want this to appear on every page, you have lots of choices that do not involve repeating this line of code..

  1. A view function can call another function.

  2. You might want to try callable objects instead of simple functions; these can subclass a common callable object that fills in this information.

  3. You can add a template context processor to put this into the context of all templates that are rendered.

  4. You could write your own decorator to assure that this is done in every view function that has the decorator.

S.Lott
Thanks for this, it is helpful. I was under the impression that it was Ok to use models in templates under some circumstances. In this case I want a template to be used as part of the page on lots of different views, but I didn't want to have to copy and paste the code to fetch the data and assign it to the template.
Tom Haigh
vikingosegundo