为啥 Django Crispy Forms 会抛出“模块‘django.forms.forms’没有属性‘BoundField’”

Posted

技术标签:

【中文标题】为啥 Django Crispy Forms 会抛出“模块‘django.forms.forms’没有属性‘BoundField’”【英文标题】:Why is Django Crispy Forms throwing "module 'django.forms.forms' has no attribute 'BoundField'"为什么 Django Crispy Forms 会抛出“模块‘django.forms.forms’没有属性‘BoundField’” 【发布时间】:2021-02-06 12:26:12 【问题描述】:

当我在表单/字段上使用“|crispy”或“|as_crispy_field”过滤器时,我收到一个错误,指出该字段没有属性 BoundField。

这工作正常,但我更新了 django/crispy 表单,我不确定我是否错过了一个技巧?没有过滤器,表单也能正常工作。

编辑:我正在使用 Django 3.1.2 和 django-crispy-forms 1.8.1。

forms.py:

from django import forms
from django.utils import timezone
from bootstrap_modal_forms.forms import BSModalForm
from backgammon import models

class MatchForm(BSModalForm):
    date_played = forms.DateField(initial=timezone.now)

class Meta:
    model = models.Match
    fields = [
        'date_played',
        'winner',
        'score'
        ]

views.py

from django.contrib.auth.mixins import PermissionRequiredMixin
from bootstrap_modal_forms.generic import BSModalCreateView
from .forms import MatchForm

class MatchCreate(PermissionRequiredMixin, BSModalCreateView):
    permission_required = 'backgammon.add_match'
    template_name = 'backgammon/match_form.html'
    form_class = MatchForm
    success_message = 'Match saved.'
    success_url = reverse_lazy('backgammon-index')

match_form.html

% load crispy_forms_tags %

<div class="container bg-light">
  <form method="post">
    % csrf_token %

     <div class="modal-body">
       % for field in form %
         <div class="form-group% if field.errors % invalid% endif %">
            field|as_crispy_field 
         </div>
       % endfor %
     </div>

     <div class="modal-footer">
       % if object %<a class="btn btn-danger mr-auto" href="% url 'match-delete' pk=object.pk %">Delete</a>% endif %
       <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
       <button type="button" class="submit-btn btn btn-primary">Save</button>
     </div>
  </form>

</div>

追溯:

Traceback (most recent call last):
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\core\handlers\base.py", line 202, in _get_response
    response = response.render()
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\template\response.py", line 105, in render
    self.content = self.rendered_content
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\template\response.py", line 83, in rendered_content
    return template.render(context, self._request)
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\template\backends\django.py", line 61, in render
    return self.template.render(context)
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\template\base.py", line 170, in render
    return self._render(context)
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\template\base.py", line 162, in _render
    return self.nodelist.render(context)
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\template\base.py", line 938, in render
    bit = node.render_annotated(context)
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\template\base.py", line 905, in render_annotated
    return self.render(context)
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\template\defaulttags.py", line 211, in render
    nodelist.append(node.render_annotated(context))
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\template\base.py", line 905, in render_annotated
    return self.render(context)
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\template\base.py", line 988, in render
    output = self.filter_expression.resolve(context)
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\django\template\base.py", line 698, in resolve
    new_obj = func(obj, *arg_vals)
  File "C:\Users\harla\Anaconda3\envs\djangoenv\lib\site-packages\crispy_forms\templatetags\crispy_forms_filters.py", line 98, in as_crispy_field
    if not isinstance(field, forms.BoundField) and settings.DEBUG:

Exception Type: AttributeError at /backgammon/match-create/
Exception Value: module 'django.forms.forms' has no attribute 'BoundField'

局部变量将“字段”变量描述为

没有脆皮过滤器,页面加载正确:

【问题讨论】:

django和crispy form有哪些版本? django 3.1.2; django-crispy-forms 1.8.1 更好地升级你的脆皮包 @ArakkalAbu 谢谢你 - conda forge 包 (anaconda.org/conda-forge/django-crispy-forms) 已经过时了,这就是我的出发点。 【参考方案1】:

我通过安装最新版本 1.11.0 解决了这个问题: https://django-crispy-forms.readthedocs.io/en/latest/install.html pip install django-crispy-forms==1.11.0

【讨论】:

我遇到这个错误是因为我安装了pip install django-crispy。我已经解决了卸载它并用pip install django-crispy-forms替换它。【参考方案2】:

正如@ArakkalAbu 评论的那样,这是一个版本可比性问题。 conda forge 中的 django-crispy-forms 版本已经过时,与最新版本的 Django 不兼容。

【讨论】:

以上是关于为啥 Django Crispy Forms 会抛出“模块‘django.forms.forms’没有属性‘BoundField’”的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Ajax 渲染 django-crispy-forms 的验证错误?

Django-crispy-forms:为 AppendedText 父 div 设置 CSS 类

python测试开发django-41.crispy-forms设计标签式导航菜单(TabHolder)

使用内联表单在 django-crispy-forms 中呈现字段错误

使用Ajax验证并提交Django表单(django-crispy-forms)

在 python 中通过 django-crispy-forms 渲染表单