【问题标题】:BootstrapError Parameter "form" should contain a valid Django FormBootstrapError 参数“form”应该包含一个有效的 Django 表单
【发布时间】:2016-04-23 05:06:34
【问题描述】:

我有一个叫做评论的应用

reviews/forms.py

from django.forms import ModelForm, Textarea
from reviews.models import Review

class ReviewForm(ModelForm):
    class Meta:
        model = Review
        fields = ['rating', 'comment']
        widgets = {
            'comment': Textarea(attrs={'cols': 40, 'rows': 15}),
        }

reviews/views.py

from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from .models import Review, Wine
from .forms import ReviewForm
import datetime

from django.contrib.auth.decorators import login_required

@login_required
def add_review(request, wine_id):
    wine = get_object_or_404(Wine, pk=wine_id)
    form = ReviewForm(request.POST)
    if form.is_valid():
        rating = form.cleaned_data['rating']
        comment = form.cleaned_data['comment']
        user_name = form.cleaned_data['user_name']
        user_name = request.user.username
        review = Review()
        review.wine = wine
        review.user_name = user_name
        review.rating = rating
        review.comment = comment
        review.pub_date = datetime.datetime.now()
        review.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse('reviews:wine_detail', args=(wine.id,)))

return render(request, 'reviews/wine_detail.html', {'wine': wine, 'form': form})

reviews/templates/reviews/wine_detail.html

{% extends 'base.html' %}
{% load bootstrap3 %}

{% block title %}
<h2>{{ wine.name }}</h2>
<h5>{{ wine.review_set.count }} reviews ({{ wine.average_rating | floatformat }} average rating)</h5>
{% endblock %}

{% block content %}
<h3>Recent reviews</h3>

{% if wine.review_set.all %}
<div class="row">
    {% for review in wine.review_set.all %}
    <div class="col-xs-6 col-lg-4">
        <em>{{ review.comment }}</em>
        <h6>Rated {{ review.rating }} of 5 by {{ review.user_name }}</h6>
        <h5><a href="{% url 'reviews:review_detail' review.id %}">
        Read more
        </a></h5>
    </div>
    {% endfor %}
</div>
{% else %}
<p>No reviews for this wine yet</p>
{% endif %}

<h3>Add your review</h3>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="{% url 'reviews:add_review' wine.id %}" method="post" class="form">
    {% csrf_token %}
    {% bootstrap_form form layout='inline' %}
    {% buttons %}
    <button type="submit" class="btn btn-primary">
      {% bootstrap_icon "star" %} Add
    </button>
    {% endbuttons %}
</form>
{% endblock %}

base.html

{% load bootstrap3 %}

{% bootstrap_css %}
{% bootstrap_javascript %}

{% block bootstrap3_content %}
<div class="container">
    <nav class="navbar navbar-default">
        <div class="navbar-header">
            <a class="navbar-brand" href="{% url 'reviews:review_list' %}">Winerama</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="{% url 'reviews:wine_list' %}">Wine list</a></li>
                <li><a href="{% url 'reviews:review_list' %}">Home</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
            {% if user.is_authenticated %}
                <li><a href="{% url 'reviews:user_review_list' user.username %}">Hello {{ user.username }}</a></li>
                <li><a href="{% url 'auth:logout' %}">Logout</a></li>
                {% else %}
                <li><a href="{% url 'auth:login' %}">Login</a></li>
                <li><a href="/accounts/register">Register</a></li>
                {% endif %}
            </ul>
        </div>
    </nav>


    <h1>{% block title %}(no title){% endblock %}</h1>

    {% bootstrap_messages %}

    {% block content %}(no content){% endblock %}
</div>

{% endblock %}

我在 html 文件中的 {% bootstrap_form form layout='inline' %} 行收到错误

知道如何解决这个问题吗?

【问题讨论】:

  • form变量为空时,就会出现这种问题。检查它是否为空。另外,请确保您已经退出 @ealeon

标签: python django forms


【解决方案1】:

您的代码目前存在一些问题,因此我将尝试使用一些 cmets 对其进行清理,因为我会编写它来为葡萄酒添加评论。

@login_required
def add_review(request, wine_id):
    wine = get_object_or_404(Wine, pk=wine_id)
    if request.POST:
        form = ReviewForm(request.POST)
    else:
        form = ReviewForm()  
    if form.is_valid():
        ### NO NEED FOR - already set as part of valid modelform ::: rating = form.cleaned_data['rating']
        ### AS WELL AS ::: comment = form.cleaned_data['comment']

        ### THIS IS NOT A FIELD IN YOUR FORM :::user_name = form.cleaned_data['user_name']
        user_name = request.user.username
        review = form.save(commit=False) # commit = False means that this instantiate but not save a Review model object
        review.wine = wine
        review.user_name = user_name # Why use this instead of a ForeignKey to user?
        review.pub_date = datetime.datetime.now() # works as long as pub_date is a DateTimeField
        review.save() # save to the DB now
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse('reviews:wine_detail', args=(wine.id,))) # THIS will redirect only upon form save
    return render(request, 'reviews/wine_detail.html', {'wine': wine, 'form': form})

现在,您看到的错误很可能与您将 request.POST 传递给表单有关,即使 request.POST 为空白;表单将尝试设置初始值,但查询字典没有与表单实际相关的值。

编辑:为了响应您的 cmets,我的下一步是尝试单独渲染每个表单字段,看看是否可以触发失败。

不要{% bootstrap_form form layout='inline' %},试试-

{% for field in form %}
    {% bootstrap_field field %}
{% endfor %}

如果这是 django-bootstrap 库尝试将 textarea 小部件和内联样式一起呈现的错误(正如我在这一点上所怀疑的那样),您还可以消除小部件参数并查看是否有修复。如果有,我建议覆盖您的模型表单的 init 方法,以便在 init 上调用 super 分配一个小部件。

【讨论】:

  • 在我看来,request.POST 仅在请求提供时传递给表单实例化。
  • 没有修复它>.
  • 在这种情况下,我建议您显示您的模板扩展的 base.html 模板。为了自己解决问题,您应该以一种简单的方式呈现视图(不使用 bootstrapform 标签)或编写一个自定义模板标签来显示该表单的对象类型。
  • 我添加了 base.html。它说它不是一个“有效的”django 表单,这意味着 review/forms.py 有问题。那是我的猜测
  • 我猜这是使用自定义 TextArea 小部件的 django-bootstrap 的错误;我在上面添加了关于如何进一步调查的建议。
【解决方案2】:

在类基础视图中

当您在错误的通用视图中使用 form_class 时,可能会出现此错误。

⮕ 打开您的 views.py,然后检查您是否在班级中设置了错误的通用视图。

示例

class ProfileUpdateView(T̶e̶m̶p̶l̶a̶t̶e̶V̶i̶e̶w̶ UpdateView):
    model = User
    form_class = forms.ProfileForm
    success_url = reverse_lazy("stories:story_list")
    template_name = 'profile.html'

    def get_object(self, queryset=None):
         return get_object_or_404(User, pk=self.request.user.id)

【讨论】:

    猜你喜欢
    • 2019-11-18
    • 2020-02-09
    • 1970-01-01
    • 1970-01-01
    • 2019-02-09
    • 1970-01-01
    • 1970-01-01
    • 2016-12-05
    相关资源
    最近更新 更多