I love Django
May 20, 2008

I'm currently working on a fairly large Django project that I think I've mentioned a couple times in the past. In that Django project there is a Person model and an Organization model. Both Persons and Organizations have email addresses. Organizations are related to Sites (through a ManyToMany field), but Persons are not (they're related to Organizations through an intermediary table). I'm currently attempting to create a contact form, so that people can email either a Person or an Organization using newforms. For security reasons, we don't want the user to actually see the email address, just the name of the Organization or Person. Fortunately, newforms has the ModelChoiceField class that you pass a queryset of options. In keeping with DRY principles, I want to be able to use a single Form regardless of whether the person is trying to email a Person or an Organization (both models have a field named 'email_address'). Unfortunately, this is where I ran into my first problem: ModelChoiceField doesn't really allow you to define the queryset dynamically, you have to define it in the form definition. Luckily I found this blog entry which provides a method to re-define the queryset in the __init__() method which allows you to change it based on the HttpRequest object. My next problem was that I only want the user to be able to email Organizations and Persons on the current Site. Since Organizations are directly related to Sites I just used the CurrentSiteManager. However since People are not directly related to Sites, and are instead related only to Organizations (through an intermediary table), I couldn't do this. Instead, I decided to try this crazy bit of code: Person.objects.filter(persontoorganization_map__organization__in=Organization.on_site.all()) Amazingly, it just worked exactly as I would have wanted it to. No fuss, no problems, just a queryset of Persons related to the current site. Go Django!
blog comments powered by Disqus