pheeper
pheeper

Reputation: 1527

How do I load multiple tables into a Django View?

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 %}

Upvotes: 1

Views: 227

Answers (1)

roob
roob

Reputation: 2529

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

Upvotes: 1

Related Questions