I have a model called 'Projects'.
Projects can be featured. If they are, they will be displayed on the home page (Projects.filter(is_featured=True))
Each project contains several slides. These slides can be featured (Slide.is_featured=True), and contain an Image model which contains the actual image.
In my home page, I would like to display a slideshow in which each slide contains the project name, and the image contained in the featured slide.
I did that by adding a method called 'featured_slide()' in my Project Model, but now I realize that I've been hitting on the DB every time, and I would like to improve that by using the 'select_related' statement.
How can I do that?
Optimally, I would like to have a field like 'featured_slide' to represent the featured slide.
I was thinking of doing something along these lines:
Projects.filter(is_featured=True).annotate(featured_slide='slides__is_featured=True').select_related(slides__image)
I know it can't be that simple (slides__is_featured is not a database field), but you get the idea.
If you want a slideshow of only those Slides
that themselves are featured as well as being related to a featured Projects
:
class Project(...):
name = models.CharField()
is_featured = models.BooleanField()
class Slide(...):
project = models.ForeignKey(Project)
is_featured = models.BooleanField()
image = models.ImageField()
to query the slides (using select_related
to avoid unnecessary queries):
slides = Slide.select_related("project").filter(is_featured=True, project__is_featured=True)
and template:
<ul>
{% for slide in slides %}
<li><img src="{{ slide.image.url }} /><span class="caption">{{ slide.project.name }}</caption></li>
{% endfor %}
</ul>
EDIT:
If you want to lookup the reverse relationship (i.e. get all the slides for a project), by default you can do the following:
project = Project.objects.get(...)
project_slides = project.slide_set.all()
You add _set
to the model name. You can make this more intuitive by adding a related_name
attribute to the relationship:
class Slide(...):
project = models.ForeignKey(Project, related_name="slideshow_slides")
and now use:
project = Project.objects.get(...)
project.slideshow_slides.all()