Проблемы с тем, что в Django inclusion_tag, похоже, есть рекурсивные вызовы

Заранее прошу прощения за длину, я хотел провести должную проверку, а также предоставить столько деталей, сколько необходимо.

У меня есть файл шаблона navbar, который включается в файл шаблона header, который затем расширяется моими визуализированными шаблонами. В навигационной панели я хочу иметь возможность иметь пузырек на пункте меню, который показывает, сколько ожидающих запросов есть для определенной модели.

Я следовал этой документации снова и снова и все еще не могу понять, в чем проблема. В моих поисках меня еще больше запутали похожие проблемы у других, но с использованием разных версий Django, поэтому я использовал Django doc в качестве основной ссылки.

Похоже, что функция (та, которая является тегом включения) вызывается рекурсивно, потому что во время отладки я заметил, что она выполняется один раз и ключ словаря request находится в контексте. Однако он выполняется во второй раз, и в этот момент нет ключа request, поэтому он терпит неудачу. Я поместил его в блок try/except, чтобы пропустить ошибку и посмотреть, что произойдет, но затем он выбрасывает ошибку "Рекурсивный предел достигнут.

".

Может ли кто-нибудь помочь с этим и выяснить, почему возникает эта ошибка?

Ошибка

  File "/Users/geoffberl/git/python/family_tools_django_site/toolpool/templatetags/tool_requests.py", line 10, in get_tool_requests_count
    owner = context['request'].user
  File "/Users/geoffberl/git/python/family_tools_django_site/venv/lib/python3.10/site-packages/django/template/context.py", line 83, in __getitem__
    raise KeyError(key)
KeyError: 'request'

Я создал пример проекта с урезанным кодом, чтобы воспроизвести проблему.

Структура проекта

(в Django 4.1)

< <
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}Family Tools{% endblock %}</title>
    <!--Bootstrap CSS-->
    <link href="{% static '/bootstrap/css/bootstrap.css' %}" rel="stylesheet">
    {% include "main/navbar.html" %}
</head>
<body>

{% block content %}

{% endblock %}

<!-- Optional Javascript -->
<script src="{% static '/bootstrap/js/jquery.js' %}"></script>
<script src="{% static '/bootstrap/js/bootstrap.js' %}"></script>
<script src="{% static 'js/jquery.bootstrap.modal.forms.min.js' %}"></script>
</body>
</html>
<
{% extends 'main/header.html' %}
{% block content %}

    <h1>Select a tool:</h1>
    <form action="{% url 'toolpool:index' %}">
        <input type="submit" value="Tool Pool"/>
    </form>

{% endblock %}

navbar.html

{% load tag_stuff %}
{% get_tool_requests_count %}
<!--Navbar-->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <a class="navbar-brand" href="{% url 'main:homepage' %}">Family Tools</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText"
            aria-controls="navbarText" aria-expanded="False" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarText">
        <ul class="navbar-nav mr-auto">
            {% if user.is_authenticated %}

                <li class="nav-item">
                    <a class="nav-link" href="/logout">Logout</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">Welcome, {{ user.username }}</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="{% url 'main:friend_requests' %}">Friend Requests</a>
                </li>
                <li class="nav-item">
                    <p>You have {{ tool_requests_count }} requests</p>
                </li>

            {% else %}

                <li class="nav-item">
                    <a class="nav-link" href="/login">Login</a>
                </li>

            {% endif %}
        </ul>
    </div>
</nav>

views.py

from django.shortcuts import render

# Create your views here.


def homepage(request):
    return render(request=request, template_name='main/home.html')

tool_requests.py

from django import template

register = template.Library()


@register.inclusion_tag('main/navbar.html', takes_context=True)
def get_tool_requests_count(context):
    owner = context['request'].user

    # Ideally some model query here which would need the 'owner' obtained above in order to get count of items.
    item_count = 12

    return {'tool_requests_count': item_count}

Вот zip-файл всего проекта, если кто-то захочет воспроизвести проблему самостоятельно. https://drive.google.com/file/d/1O8jwjyMvzKD4Ef0-6uN-Ju9N2YAS8R7U/view?usp=sharing

Для полного раскрытия информации, это было первоначально опубликовано на Reddit r/Django, но, похоже, не имеет много просмотров. https://www.reddit.com/r/django/comments/xg0gwr/help_with_providing_model_data_to_a_partial/

Благодаря philgyford на Reddit, эта проблема была решена. Оказывается, я неправильно использовал тег Inclusion, в то время как следовало использовать тег Simple.

Обновлен tool_requests.py

from django import template

register = template.Library()


@register.simple_tag(takes_context=True)
def get_tool_requests_count(context):
    owner = context['request'].user

    # Ideally some model query here which would need the 'owner' obtained above in order to get count of items.
    item_count = 12

    return item_count
Вернуться на верх