首页 > 解决方案 > 包含第二个 HTML 模板时 Django 模板中的递归错误

问题描述

你好。我刚刚完成我的第一个 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>&times;</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>&times;</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>&times;</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 在尝试打开带有表单的任何页面(包含该文件)时显示以下错误:

/my_app/other_template_file.html 处的 RecursionError
超出最大递归深度

我认为我做的一切都是正确的,但是......我错过了什么吗?

我的具体问题是:

  1. 为什么 Django 抱怨递归?
  2. 我该怎么做才能使上述模板按预期工作?
    具体来说:我想要一个“通用”模板来显示所有表单错误并将其包含在我的其他模板中。

基本信息:


编辑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内容放入模板文件中,一切都会按预期工作......所以现在的问题是:为什么当我直接写入模板时代码可以工作,而不是包含在内时?

标签: djangopython-3.xdjango-templates

解决方案


推荐阅读