Проблемы с тем, что в 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