Hello. Я просто заканчиваю свой первый проект Django, и он идет отлично. Однако у меня есть небольшая проблема при включении шаблона HTML в другой.
Я бы хотел, чтобы отображался один файл со всеми ошибками формы, поэтому мне не нужно писать одно и то же снова и снова в каждой форме. Итак, у меня есть этот маленький шаблон:
my_app / form_error_messages.html:
{% if form.non_field_errors %}
<div class="col-sm-12 alert alert-danger alert-dismissable fade show" role="alert">
<button type="button" class="close" data-dismiss="alert" >
<span>×</span>
</button>
<div class="">
{{ form.non_field_errors }}
</div>
</div>
{% endif %}
{% for field in form.hidden_fields %}
{% if field.errors %}
<div class="col-sm-12 alert alert-danger alert-dismissable fade show" role="alert">
<button type="button" class="close" data-dismiss="alert" >
<span>×</span>
</button>
<div class="">
{{ field.label }}: {{ field.errors }}
</div>
</div>
{% endif %}
{% endfor %}
{% for field in form.visible_fields %}
{% if field.errors %}
<div class="col-sm-12 alert alert-danger alert-dismissable fade show" role="alert">
<button type="button" class="close" data-dismiss="alert" >
<span>×</span>
</button>
<div class="">
{{ field.label }}: {{ field.errors }}
</div>
</div>
{% endif %}
{% endfor %}
И на каждом из моих других шаблонов у меня есть что-то вроде этого:
my_app / other_template_file.html
{% extends "base.html" %} <!-- All HTML templates extends from this file -->
{% block "my_block" %} <!-- This injects the block into my base template file -->
{% include 'my_app/general_info.html' %} <!-- This template works so far -->
<!--
HTML code specific to my template
-->
<form method="POST">
{% csrf_token %}
{% include "my_app/form_error_messages.html" %} <!-- THIS IS BRAKING MY PAGES -->
{{ form.as_p }}
<input type="submit" value="Ok"/>
</form>
{% endblock %}
my_app / views.py
def my_view(request):
if request.method == 'POST':
form = MyEntryForm(request.POST)
if form.is_valid():
form.save()
return HttpresponseRedirect(reverse('my_app:index'))
else:
form = MyEntryForm()
return render(request, 'my_app/other_template_file.html', {'form':form})
my_app / forms.py
def MyEntryForm(forms.ModelForm):
class Meta:
model = MyModel
fields = '__all__'
my_app / models.py
class MyModel(models.Model):
title = models.CharField(max_length=100, db_index=True)
text = models.TextField()
Соответствующая файловая структура:
my_project/
|
+-- my_project/
| |
| +-- __init__.py
| +-- settings.py
| +-- urls.py
| +-- wsgi.py
|
+-- my_app/
| |
| +-- __init__.py
| +-- forms.py
| +-- models.py
| +-- urls.py
| +-- views.py
| +-- templates/
| |
| +-- my_app/
| |
| +-- other_template_file.html
| +-- form_error_messages.html
|
+-- templates/
|
+ -- base.html
Соответствующие настройки:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates')
# ...
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATES_DIR,],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Перед включением my_app/form_error_messages.html
все работает нормально, но после его включения Django показывает следующую ошибку при попытке открыть любую страницу с формой (с включенным этим файлом):
RecursionError в /my_app/other_template_file.html
максимальная глубина рекурсии превышена
Мне кажется, я все делаю правильно, но ... я что-то упустил?
Мой конкретный вопрос:
- Почему Джанго жалуется на рекурсию?
- Что я могу сделать, чтобы вышеуказанный шаблон работал должным образом?
В частности: я хочу, чтобы «общий» шаблон отображал все ошибки формы и включал его в другие мои шаблоны.
Общая информация:
- Python: 3,6
- Джанго: 2,0
- Я использую сервер разработки, чтобы проверить это перед переходом в производство.
Редактировать 1:
Трассировка стека, которую показывает мне Django, составляет более 2K строк! (Я думаю, что было бы плохой идеей опубликовать это здесь в полном объеме). Однако здесь я поместил некоторые строки трассировки стека:
Template error:
In template D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\forms\templates\django\forms\widgets\attrs.html, error at line 1
maximum recursion depth exceeded
1 : {% for name, value in widget.attrs.items %}{% if value is not False %} {{ name }} {% if value is not True %} ="{{ value|stringformat:'s' }}"{% endif %}{% endif %}{% endfor %}
Traceback:
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\smartif.py" in translate_token
175. op = OPERATORS[token]
During handling of the above exception ('value'), another exception occurred:
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\base.py" in __init__
767. self.literal = float(var)
During handling of the above exception (could not convert string to float: 'value'), another exception occurred:
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\core\handlers\exception.py" in inner
35. response = get_response(request)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\core\handlers\base.py" in _get_response
128. response = self.process_exception_by_middleware(e, request)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\core\handlers\base.py" in _get_response
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view
21. return view_func(request, *args, **kwargs)
File "D:\Users\MBARRANCA\Documents\PythonProjects\my_projects\project01\my_django_project\my_app\views.py" in cargar_archivo_leads_v2
652. return render(request, 'leads/cargar_archivo_leads.html', {'form':form})
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\shortcuts.py" in render
36. content = loader.render_to_string(template_name, context, request, using=using)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\loader.py" in render_to_string
62. return template.render(context, request)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\backends\django.py" in render
61. return self.template.render(context)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\base.py" in render
175. return self._render(context)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\base.py" in _render
167. return self.nodelist.render(context)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\base.py" in render
943. bit = node.render_annotated(context)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\base.py" in render_annotated
910. return self.render(context)
... (a lot more of these)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\base.py" in parse
481. compiled_result = compile_func(self, token)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\defaulttags.py" in do_if
955. condition = TemplateIfParser(parser, bits).parse()
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\defaulttags.py" in __init__
888. super().__init__(*args, **kwargs)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\smartif.py" in __init__
166. mapped_tokens.append(self.translate_token(token))
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\smartif.py" in translate_token
177. return self.create_var(token)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\defaulttags.py" in create_var
891. return TemplateLiteral(self.template_parser.compile_filter(value), value)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\base.py" in compile_filter
568. return FilterExpression(token, self)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\base.py" in __init__
653. var_obj = Variable(var)
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\template\base.py" in __init__
788. self.literal = mark_safe(unescape_string_literal(var))
File "D:\Users\MBARRANCA\AppData\Local\Continuum\Anaconda3\lib\site-packages\django\utils\functional.py" in wrapper
196. return func(*args, **kwargs)
Exception Type: RecursionError at /my_app/other_template_file
Exception Value: maximum recursion depth exceeded
Редактировать 2:
Если я добавлю содержимое form_error_messages.html
в мой файл шаблона, все будет работать так, как ожидалось ... Итак, теперь возникает вопрос: почему код работает, когда я непосредственно записан в шаблон, а не когда он включен?