Search code examples
djangotemplatesjoinmodels

Django query for linking related data in template


I have two tables of data in a Django app, one containing shipping vessel details and the other containing offers related to individual vessels. My models are as follows:

class Vessel(models.Model):
    name = models.CharField(max_length=64)
    image = models.CharField(max_length=64)
    vesseltype = models.ForeignKey(VesselType)
    capacity = models.IntegerField()
    length = models.FloatField()
    beam = models.FloatField()
    speed = models.IntegerField()
    activities = models.CharField(max_length=256)
    category = models.IntegerField()
    display_order = models.IntegerField()
    published = models.BooleanField()
    def __unicode__(self):
        return self.name

class Offer(models.Model):
    vessel = models.ForeignKey(Vessel)
    description = models.CharField(max_length=128)
    date = models.DateField()
    duration = models.IntegerField()
    itinerary = models.TextField()
    price = models.IntegerField()
    display_order = models.IntegerField()
    link = models.URLField()
    published = models.BooleanField()
    def __unicode__(self):
        return self.description

In my views.py I have the following code:

def home(request):
    vessels = Vessel.objects.filter(published='y').order_by('display_order')
    offers = Offer.objects.filter(vessel__published__exact='y').filter(published='y').order_by('display_order')
    t = loader.get_template('index.html')
    c = Context({
        'vessels' : vessels,
        'offers' : offers,
    })

In the template I need to display multiple divs each containing the vessel name, some of the vessel details and any number of offers related to that vessel.

I've looked at queries trying to link the offers in with each vessel and I've also tried identifying the vessel name inside loop code in the template to just display an offer if the vessel.id and offer.vessel match up.

So far, nothing has been successful with just getting errors on the query side and separate lists of vessel names and offers by going the template way. How do I join this information so I could just use something like this in the template:

for offer in offers:
    offer.vessel.name
    offer.vessel.category
    offer.description
    offer.price

or am I expecting too much? Been at this for several hours and can't find a solution in the docs but it's probably obvious. Changing the query, the view code or the template is not a problem.


Solution

  • The answer is to change your view code. You want a queryset like Offer.objects.all().select_related(). select_related will make sure you don't hit the database every time your loop executes because it will follow foreign keys to the end before executing a query.

    You're also using the wrong template syntax. It needs to be something like:

    {% for object in object_list %}
    {{ object.attribute }}
    {% endfor %}