2

New to coding so apologies if this has been covered. Spent the last few evenings on Django's docs, YouTube, Google and here trying all kinds of ways to fix this.

I have a model Route which is related to Driver and I am trying to display all the routes with the relevant drivers associated with that route on my template. However at the moment all I can get is the data from the Route model, not the associated Driver.

Would appreciate any help on this as I'm struggling to get my head around it!

Models.py

class Driver(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
    first_name = models.CharField(max_length=120, blank=True, null=True)
    last_name = models.CharField(max_length=120, blank=True, null=True)
    tel = models.CharField(max_length=120, blank=True, null=True)
    slug = models.SlugField(max_length=120, unique=True)
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
    updated = models.DateTimeField(auto_now_add=False, auto_now=True)

    def __str__(self):
        return self.first_name

    def save(self, *args, **kwargs):
        self.slug = slugify(self.first_name)
        super(Driver, self).save(*args, **kwargs)

class Route(models.Model):
    leave_from = models.CharField(max_length=120, blank=True, null=True)
    destination = models.CharField(max_length=120, blank=True, null=True)
    date = models.DateField(auto_now_add=False, auto_now=False)
    time = models.TimeField(auto_now_add=False, auto_now=False)
    drivers = models.ForeignKey(Driver, on_delete=models.CASCADE)

    def __str__(self):
        return self.leave_from

Views.py

def drivers(request):
    qs = Route.objects.all().select_related()
    context = {
        "qs": qs,
        }
    return render(request, 'drivers.html', context)

Template

{% for instance in qs %}
    <p>{{ instance.user }} <br> {{ instance.first_name }} {{ instance.last_name }} {{ instance.tel }} {{ instance.destination }} </p>

    <iframe width="600" height="450" frameborder="0" style="border:0" src="https://www.google.com/maps/embed/v1/directions?origin={{ instance.leave_from }}
    &destination={{ instance.destination }}
    &key=AIzaSyAyuIOgVteQ0NLxCCTz4axRmta_JL3OVL4">
    </iframe>
{% endfor %}

I have tried .prefetch_related('driver') and a few other combinations but I either only get the Route data or an error.

Thanks in advance.

Disclaimer I did ask this a couple of days back but without the template and hadn't got any further replies after I edited it in. I'm just at a brick wall so would appreciate any pointers as to where I've gone wrong.

t_om
  • 35
  • 1
  • 5

1 Answers1

0

Here:

{% for instance in qs %}
    <p>{{ instance.user }} <br> {{ instance.first_name }} {{ instance.last_name }} {# etc #}

instance is a Route object, the attributes you're looking for belongs to Driver objects. You want:

{% for route in qs %}
    {% with driver=route.drivers %} {# XXX should be named 'driver' #}
    <p>{{ driver.user }} <br> {{ driver.first_name }} {{ driver.last_name }} 
{# etc #}

While we're at it: Route.drivers should really be renamed to Route.driver (it's a foreign key, not a many2many, so you have one single driver per route, so you want a singular not a plural that denotes a collection), and you should use .select_related("driver", "driver__user") here (cf What's the difference between select_related and prefetch_related in Django ORM? for when to use select_related or prefetch_related).

Also, is there any reason to duplicate the first_name and last_name in your Driver model when they already exist in User ? Oh and yes, in Route, you add auto_now_add=False and auto_now=False to your date fields, this is useless since those are the default.

bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
  • Amazing thank you that works! Thanks also for the pointers on the code, much appreciated :) – t_om Nov 24 '17 at 21:54