reverse search in template

Hej!

I have a model for institutions which includes an attribute for parent institutions related to itself

class Institution(models.Model):
    name = models.CharField(
        max_length=200,
    )
    parent_institution = models.ForeignKey(
        "self",
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        help_text=_("if applicable"),
    )

in my template for a DetailView I want not only the parents shown but the ‘childern’ so all institutions where the institution id of the shown institution equals the parent_institution id of one or multiple institutions in my data base.

I tried

                {% if institution.id == institution.all.parent_institution.id %}
                    {{institution.name}}
                {% endif %}

which doesn’t show me anything.

or

                {% if institution.all.id == institution.parent_institution.id %}
                    {{institution.name}}
                {% endif %}

which gives me the name of the ‘current’ institution, not its childre.

same as:

´´´
{% for child in institutions.all %}
{% if child.id == institution.parent_institution.id %}
{{institution.name}}
{% endif %}
{% endfor %}
´´´

Does anyone know how to achieve that? Is that even possible?

Yes it’s possible.

However, I’m not clear on exactly what you want to see. Is this a multi-level structure where you want to recursively display all levels in a tree-like structure? Or is this strictly a 2-level structure?

Assuming the simple case - a 2-level structure, your root nodes might be described as:
institutions = Institution.objects.filter(parent_institution__isnull=True).prefetch_related('parent_institution_set')

Then, as you’re iterating over institutions, the set of child-nodes to any parent would be child_nodes = institution.parent_institution_set.all() (where institution is a single element within the institutions queryset).
Or if you’re iterating over that set in the template, your inner loop might be:
{% for child_node in institution.parent_institution_set.all %}

(Side note: If you’re working with an n-level structure, you’ll want to look at other mechanisms for creating / managing this hierarchical data. See treebeard for some ideas.)

                {% if institutions.all.id == institutions.parent_institution.id %}
                    {% for child_node in institutions.parent_institution_set.all %}
                        {{child_node.name}}
                    {% endfor %}
                {% endif %}

If I try it like this I’m not getting anything. Doesn’t matter if I use institutions or institutions_child

class InstitutionDetail(DetailView):
    model = Institution

    def get(self, request, *args, **kwargs):
        institutions_child = Institution.objects.filter(parent_institution__isnull=True).prefetch_related('parent_institution_set')
        institutions = get_object_or_404(Institution, pk=kwargs['pk'])

        context = {'institutions_child': institutions_child, 'institutions': institutions}

        return render(request, 'stakeholders/institution_detail.html', context)

You need to remove that outer if. It’s not needed here. The for tag replaces it.

still nothing :confused:

is my view correct?

I need a better perspective of what exactly you’re trying to display here. Seeing your complete template is going to help.

Your view may or may not be ok, I don’t have enough information to tell.

What do you think “institutions_child” and “institutions” contain?

I have a model to create single institutions (Institution) and can connect it to a parent institution, via parent_institution (self).

So I have the institution A, which is parent to b, c, d (All themselves single institutions with an own detail view.) In the detail view of b I have the section ‘parent institution’ where I get A as a a result, including a link to the detail view of A.

<p><b>Parent institution: </b>
    {% if institution.parent_institution %}
    <a href="{% url 'stakeholders:institution_detail' institution.parent_institution.id %}">
        {{institution.parent_institution}}
    </a>
    {% endif %}
</p>

Following this link I get to the detail view of A where I want a section with the child institutions. There should b, c, d be listed with a link each.

I added a related name to the parent_institution

class Institution(models.Model):
    name = models.CharField(
        verbose_name=_("Name of the institution"),
        max_length=200,
    )
    parent_institution = models.ForeignKey(
        "self",
        verbose_name=_("Parent institution"),
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        help_text=_("if applicable"),
        related_name="child",
    )

normally I can follow the ForeignKey in the opposite direction via this related_name.

<p><b>Child institution: </b>
        {{institution.child.name}}
</p>

but in this case this is not working. Therefor did I try the above mentioned parts without any result.

I hope this is clearer now :slight_smile:

<p><b>Child institution: </b></p>
<ul>
    {% for child in institution.child.all %}
        <li>{{ child.name }}</li>
    {% endfor %}
</ul>

solved my problem :slight_smile:
Thanks for all your time!