How to query from 2 Models in Class based views in django?

Viewed 42

I have a model Log and another model Solutions and I am using DetailView to display details of each log

Each log can have many solutions. There is a log field in the Solutions model that is Foreign Key to Log model..

Now how do I access both Log model and Solutions of that particular log in the same html template if I want to display all the solutions of that particular log below the details of the log

models.py:

class Log(models.Model):
    title = models.CharField(blank=False, max_length=500)
    content = models.TextField(blank=False)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    slug = models.SlugField(max_length=50, null=False, unique=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE,null=True, blank=True)
    image = models.ImageField(
        upload_to='images', blank=True)

    def save(self, *args, **kwargs):
        super().save()
        self.slug = self.slug or slugify(self.title + '-' + str(self.id))
        super().save(*args, **kwargs)

    class Meta:
        verbose_name = ("Log")
        verbose_name_plural = ("Logs")

    def __str__(self):
        return f"{self.title}"


    def get_absolute_url(self):
        return reverse("log-detail", kwargs={"question": self.slug})
    

class Solutions(models.Model):
    log = models.ForeignKey(
        Log, on_delete=models.CASCADE, blank=True, null=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE,null=True, blank=True)
    solution = models.TextField(null=True)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    slug = models.SlugField(max_length=50, null=False, blank=True)
    image = models.ImageField(
        upload_to='images', blank=True)

    def save(self, *args, **kwargs):
        self.slug = self.slug or slugify(self.solution)
        super().save(*args, **kwargs)

    class Meta:
        verbose_name = ("Solution")
        verbose_name_plural = ("Solutions")

    def __str__(self):
        return f"  {self.solution} "

views.py:

class LogDetailView(DetailView):
    model = Log
    slug_url_kwarg = 'question'
    slug_field = 'slug'

log_detail.html:

{% extends 'log/base.html' %}
{%load crispy_forms_tags %}
{% block content %}

<title>Error Logger - {{object.title}}</title>

<div class="main container mt-4 p-3 mb-4">
<img style='display:inline;' class='rounded-circle account-img' src="{{ object.author.profile.avatar.url }}" alt="">

  <h1 style='display:inline;'>
    <a href="#">{{ object.title }}</a>
  </h1>


  <p>Author: <a href="{% url 'profile' object.author   %}">{{ object.author }}</a></p>
  <p>Date and time of creation: {{ object.created }}</p>
  <span> Details </span>:
  <p class="big ml-4">{{ object.content }} <br />

  {% if object.image %}
  <img style="width: 20vw" class="mt-4" src="{{ object.image.url }}" alt="image" />
  {% else %} 
  {% endif %}

  </p>


</div>
<br />

<a
  class="btn btn-outline btn-info button-solution"
  href="#"
  >Add solution</a
>
1 Answers

You can enumerate over these in the template by accessing the relation in reverse, this is normally modelname_set, unless you set a related_name=…. So in this case it is solutions_set:

{% for solution in object.solutions_set.all %}
    {{ solution }}
{% endfor %}

If the ForeignKey has a related_name=… [Django-doc], for example with:

class Solutions(models.Model):
    log = models.ForeignKey(
        Log,
        on_delete=models.CASCADE,
        blank=True,
        null=True,
        related_name='solutions'
    )
    # …

Then we access this with:

{% for solution in object.solutions.all %}
    {{ solution }}
{% endfor %}

Note: normally a Django model is given a singular name, so Solution instead of Solutions.

Related