Sunday, February 26, 2012

Re: Django and models with multiple foreign keys

On Feb 26, 4:03 am, trudoe <martinga...@gmail.com> wrote:

> In brief, can someone please help me to get a summary of all the trips
> and activities? What's the best way to accomplish that? Is the model
> correct?

From the looks of it, you might benefit if the m2m relation would be
hand-defined, and activities then relate to that model. Something
like:

class Trip:
...
class Destination:
...

class TripDestination:
trip = models.ForeignKey(Trip, related_name='destination')
destination = models.ForeignKey(Destination)
class Meta:
unique_together = ('trip', 'destination')

class Activity:
at = models.ForeignKey(TripDestination, related_name='activities')

Now, the correct way to display all this data is to do (pseudo-code):
{% for trip_dest in trip.destinations %}
{{ trip_dest.destination }}
{% for act in trip_dest.activities %}
{{ act }}
...

Be careful, the above generates a lot of queries. You would benefit a
lot by using 1.4 beta and its prefetch_related feature. In 1.3 you can
do the prefetching by hand in your view code by something similar to
what you do currently. However I usually assign the prefetched list
directly to the related model. Something like:

trips = list(Trip.objects.all())
# Make sure every trip has a list of destinations
[setattr(trip, 'trip_dest_lst', []) for trip in trips]
# This will allow fast joining, we can find the trip by its PK fast...
trip_dict = dict([(trip.pk, trip) for trip in trips])
trip_dests =
TripDestination.objects.filter(trip__in=trips).select_related('destination')
# Here we append the trip destinations fetched above to related
trip's trip_dest_lst
[trip_dict[td.trip_id]trip_dest_lst.append(td) for td in trip_dests]

Now every trip should have (possibly empty) list of trip destinations.
You will still need to do the same for the activities per trip
destination, exactly same logic applies. Note that the above is not
tested, it is almost guaranteed to not work correctly.

In the template you would of course use the trip.trip_dest_list
instead of trip.destinations.all().

- Anssi

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

No comments:

Post a Comment