Django : Only display model items that match with for each category

Question:

Here are the models I’ve created

class Jeu(models.Model):
    nom = models.CharField('Nom du jeu', max_length=100)
    logo = models.ImageField(blank=True)


class Course(models.Model):
    jeu = models.ForeignKey(Jeu, verbose_name='Nom du jeu', on_delete=models.CASCADE)
    ligue = models.ForeignKey(Ligue, on_delete=models.CASCADE)
    circuit = models.ForeignKey(Circuit, on_delete=models.CASCADE)
    date_evenement = models.DateTimeField("Date de la course")

Here is the view :

def home(request):
    courses_a_venir = Course.objects.filter(date_evenement__gte = datetime.today()).order_by('date_evenement')
    courses_passees = Course.objects.filter(date_evenement__lt = datetime.today()).order_by('-date_evenement')[:3]
    jeux = Jeu.objects.all()
    return render(request, 'base_site/home.html', context={'title': 'Accueil', 'courses_a_venir': courses_a_venir, 'jeux': jeux, 'courses_passees': courses_passees})

And then here is the HTML code :

{% for jeu in jeux %}
<h3>{{ jeu.nom }}</h3><br>
<div class="row row-cols-1 row-cols-md-3 g-4">
  {% for course in courses_a_venir %}
  <div class="col">
    <div class="card">
      <!--<img src="..." class="card-img-top" alt="...">-->
      <div class="card-body">
        <h5 class="card-title">{{ course.jeu }}</h5>
        <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional
          content. This content is a little bit longer.</p>
      </div>
      <div class="card-footer">
        <small class="text-muted">{{ course.date_evenement }}</small>
      </div>
    </div>
  </div>
  {% endfor %}
</div><br>
{% endfor %}
<br><br>

What I’d like to do, is to display only the "Course" items that match with the name of the "Jeu". I know that I have to insert an if statement in the HTML code, and I tried different things, such as :

    {% for jeu in jeux %}
      <h3>{{ jeu.nom }}</h3><br>
      <div class="row row-cols-1 row-cols-md-3 g-4">
      {% for course in courses_a_venir %}
      {% if course.jeu == jeu.nom %}
        .....
      {% endif %}
      .....

But that doesn’t seem to work…

The actual status of the HTML page

Asked By: Madal

||

Answers:

One robust way is to define those queries as model methods:

class Jeu(models.Model):
    nom = models.CharField('Nom du jeu', max_length=100)
    logo = models.ImageField(blank=True)

    def courses_a_venir():
        return self.course_set.filter(date_evenement__gte = datetime.today()).order_by('date_evenement')

    def courses_passees():
        return self.course_set.filter(date_evenement__lt = datetime.today()).order_by('-date_evenement')[:3]

You can then remove the context variables from your view:

def home(request):
    jeux = Jeu.objects.all()
    return render(
        request,
        'base_site/home.html',
        context={'title': 'Accueil',  'jeux': jeux,}
    )

and simply do the following in your template:

{% for jeu in jeux %}
    <h3>{{ jeu.nom }}</h3><br>
    <div class="row row-cols-1 row-cols-md-3 g-4">
    {% for course in jeu.courses_a_venir %}
        <p>{{ course.date_evenement }}</p>
    {% endfor %}
{% endfor %}
Answered By: Selcuk

I believe this can be solved using Django’s built in template tag regroup:

https://docs.djangoproject.com/en/4.1/ref/templates/builtins/#regroup

Answered By: Özer
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.