WebFaction
Community site: login faq

I have a generic detail view serving content for 'project' to an HTML template with the following code:

{% for detail in project.projectdetail_set.all %}
    {% for image in detail.projectdetailimage_set.all %}
        do something with image
    {% endfor %}
{% endfor %}

and my models look like:

class Project(models.Model):
    name = models.CharField(max_length=1000)
    start_date = models.DateField()
    abstract = models.TextField()
    abstract_image = models.ImageField(storage=PROJECT_STORAGE)

    def __str__(self):
        return self.name

class ProjectDetail(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)
    name = models.CharField(max_length=1000)
    text = models.TextField()

    def __str__(self):
        return self.name

class ProjectDetailImage(models.Model):
    detail = models.ForeignKey(ProjectDetail, on_delete=models.CASCADE)
    image = models.ImageField(storage=PROJECT_STORAGE)

It looks like generic detail view only arranges for backward lookup on the 'project' via .projectdetail_set.all but not on the 'detail' as the HTML for .projectdetailimage_set.all just never shows up in the HTML source. I am wondering then what is the proper way to handle nested ForeignKeys like this, basically like a Book > Section > Chapter structure where a Book has several Sections and a Section has several Chapters and Chapters are only associated with Sections and Sections are only associated with Books.

asked 07 Aug, 12:48

tfhughes's gravatar image

tfhughes
112
accept rate: 0%

What does your view code look like?

(08 Aug, 17:21) seanf ♦♦ seanf's gravatar image

Here is my view code:

from django.views import generic
from .models import Project

class IndexView(generic.ListView):
    template_name = 'projects/index.html'
    context_object_name = 'object_list'

    def get_queryset(self):
        return Project.objects.all().order_by('start_date').reverse()

class DetailView(generic.DetailView):
    model = Project
    template_name = 'projects/detail.html'
(08 Aug, 18:06) tfhughes tfhughes's gravatar image

I wonder if you need to get_context_data method with your view classes? The generic view docs don't explicitly state that it's a requirement, but all of their examples seem to include it.

(08 Aug, 19:39) seanf ♦♦ seanf's gravatar image

Probably yes but I am unsure how to do that given that I need access to the project detail images for a given detail in a loop. The context has 'project' defined and for generic detail views Django makes all details available with 'project.projectdetail_set.all' (see HTML template above). I found some information here about '*_set.all' (https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Generic_views and search for 'The one interesting thing') but it looks like Django might only do this backwards lookup for the matching object, in this case 'project', and not for any lower object layer, for example not for 'detail'. Maybe I need to overwrite the get_object method of my DetailView and somehow explicitly set the equivalent of 'detail.projectdetailimage_set.all'?

(08 Aug, 21:33) tfhughes tfhughes's gravatar image

it looks like Django might only do this backwards lookup for the matching object, in this case 'project', and not for any lower object layer, for example not for 'detail'.

That doesn't seem likely to me. The objects returned by whatever_set.all are full objects with all of the methods and properties that they should have. So, since you have your ProjectDetail objects, you should also have their related ProjectDetailImage objects.

(08 Aug, 21:58) seanf ♦♦ seanf's gravatar image

OK. Could it be that I need to use prefetch_related when setting up my models? I just recently found a similar example here https://stackoverflow.com/questions/25236199/django-reverse-lookup-chaining-queryset. Maybe the query just wasn't performed and so the data expected in 'detail.projectdetailimage_set.all' by the time I get inside the HTML template doesn't exist?

(08 Aug, 22:11) tfhughes tfhughes's gravatar image

That doesn't look like the same thing to me. That SO question is trying to get all of the images for a designer, without hitting the projects in the middle.

Your example isn't leaving out the middle bit. You're getting all of the details for for a project , and then getting all of the images for those details.

When you include {% for image in detail.projectdetailimage_set.all %} in your template, you're running the queryset right there, so you should have the objects you need.

If you play around with your models in the admin shell, do you get the expected results for all of those methods?

(08 Aug, 22:27) seanf ♦♦ seanf's gravatar image

OK. Ugh ... I spent entirely too long staring at this to not have seen the issue sooner. Of course you wouldn't have been able to see it because I only included the line 'do something with image' in my HTML code above. The issue is with using 'image.url' rather than 'image.image.url'. And apparently even with DEBUG on it silently fails with the former. It wasn't until your last comment got me digging someplace else where I then realized it. I thank you very much for thinking about this with me!

(09 Aug, 12:26) tfhughes tfhughes's gravatar image
showing 5 of 8 show 3 more comments

Sean F really helped me along here. The issue was with using 'image.url' rather than 'image.image.url' in code labeled with 'do something with image' in the HTML template above.

permanent link

answered 09 Aug, 12:29

tfhughes's gravatar image

tfhughes
112
accept rate: 0%

Your answer
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "title")
  • image?![alt text](/path/img.jpg "title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Question tags:

×882

question asked: 07 Aug, 12:48

question was seen: 87 times

last updated: 09 Aug, 12:29

WEBFACTION
REACH US
SUPPORT
AFFILIATE PROGRAM
LEGAL
© COPYRIGHT 2003-2016 SWARMA LIMITED - WEBFACTION IS A SERVICE OF SWARMA LIMITED
REGISTERED IN ENGLAND AND WALES 5729350 - VAT REGISTRATION NUMBER 877397162
5TH FLOOR, THE OLD VINYL FACTORY, HAYES, UB3 1HA, UNITED KINGDOM