1

I'm working through my first Django project (aside from a couple tutorials) and am stuck on how to accomplish this. For simplicity I'll use an Excel analogy to explain what I'm trying to do. I have 7 buttons across row 1 (TOP Model). Clicking on any of those buttons then brings up a list of 5 items in column A (SIDE Model) which all have corresponding items in rows 2-6 (BODY Model). In the View I can get the SIDE Model to load through the TOP Model primary key, but can't figure out how to connect the BODY Model since it's dependent on the SIDE Model.

VIEW

def details(request, pk):
    top = TOP.objects.filter().order_by('-modified_date')
    middle= MIDDLE.objects.filter(TOP_id__pk=pk)
    body = BODY.objects.filter(??????????)
   return render(request, 'details.html', {'top': top, 'middle': middle,
                                                      'body': body})

MODEL

class TOP(models.Model):
    title = models.CharField(max_length=200)

class MIDDLE(models.Model):
    TOP= models.ForeignKey('mysite.TOP', related_name='middle')
    title = models.CharField(max_length=200)

class BODY(models.Model):
    TOP= models.ForeignKey('mysite.TOP', related_name='indicators')
    MIDDLE= models.ForeignKey('mysite.MIDDLE', related_name='indicators')
    title = models.CharField(max_length=200)

TEMPLATE

{% block content %}
<div>

    <div class="TOP-container">
        {% for tops in top %}
            <div class="tops"><a href="{% url 'details' pk=tops.pk %}">{{ tops.title }}</a></div>
        {% endfor %}
    </div>

    {% for middles in middle %}
        <div class="middle-container">
            <div class="middles">{{ middles.title }}</div>
            {% for bodys in body %}
                <div class="bodys">{{ body.title }}</div>
            {% endfor %}
        </div>
    {% endfor %}

</div>
{% endblock %}

1 Answer 1

1

You need to access the middle and body objects using the foreign key related name.

If I understand your question correctly:

  • You only want to display MIDDLE (SIDE) elements associated with the selected TOP element.
  • You only want to display BODY elements associated with the displayed MIDDLE elements

To accomplish this you need to:

  1. Keep track of which TOP element is selected
  2. Loop through only the MIDDLE object with a foreign key pointing to this TOP object

Therefore, your loop will look like this:

{% for middle in selected_top.middle.all %}
    <div class="middle-container">
        <div class="middles">{{ middle.title }}</div>
        {% for body in middle.indicators.all %}
            <div class="bodys">{{ body.title }}</div>
        {% endfor %}
    </div>
{% endfor %}

Note the template syntax used to access the foreign key by its related_name:

<object>.<related_name>.all

A few other notes:

  • Its standard to use a plural variable name to represent a set of objects and a singular name to represent a single element in the set; you did the opposite
  • You are mixing the use of MIDDLE and TOP
  • You only need to pass the set of TOP objects to the view
Sign up to request clarification or add additional context in comments.

1 Comment

That was pretty painless and makes complete sense, thanks! I've also corrected the use of single/plural variable names, which definitely reads better now. I've been using the Django Girls Tutorial project that I completed previously and they had them flipped, so thanks for pointing that out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.