模板无法从视图中找到表单数据

时间:2014-01-19 15:23:26

标签: html django forms

我已经阅读了django教程,并尝试了许多不同的方法来处理django中的表单,但它似乎没有按预期工作。我已经做了大量的研究和阅读,包括搜索谷歌和stackoverflow,但我似乎无法让它工作,也许我不像你们其他人那么尖锐所以这就是为什么我要问你。

我正在创建一个表单来处理一些数据,然后当用户点击按钮时我想要一个新页面来显示即将保存的信息。用户单击按钮后,我将获得模板,但在标题和说明字段中没有值。

更详细地描述一下: 1.我正在输入url / register / user / new,如果没有发送任何POST数据,则会显示该表单 2.填写表单并且用户单击按钮,视图验证数据并将用户发送到/ register / user / success,由不同的视图处理。此视图加载模板,该模板用于向用户显示用户输入的数据,以确保其正确无误。

我认为两个视图之间的数据丢失但如果我只使用一个视图并尝试在POST数据存在时渲染另一个模板,我仍然只能看到表单,这样也无法工作。我也试过使用args和kwargs参数来渲染函数而没有任何运气。

这是第一个视图的视图代码:

def newUser(request):
    if request.method == 'POST':
        form = NewUserForm(request.POST)
        if form.is_valid():
            title = form.cleaned_data['username']
            description = form.cleaned_data['position']
            category = form.cleaned_data['department']
                # this is the first thing i tried, since the documentation states that you should always send a httpresponseredirect to avoid the user clicing twice on the form
                return HttpResponseRedirect("/register/user/success")

                # this is another attempt i used but it just displays the same form
                render(request, "registration_submitted.html", {'username': 'username'})
    else:
            form = NewUserForm()

def newUserSuccess(request):
    render_to_respone("newuser_submitted.html")

模板代码非常简单,我只是尝试使用双卷曲括号打印出一个变量,如:{{username}},它不输出任何内容。

这是模板代码:

{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
    <title>Story successfully submitted</title>
    <script src="{% static 'js/transition.js' %}" type="text/javascript"></script>
    <script src="{% static 'js/collapse.js' %}" type="text/javascript"></script>
    <script src="{% static 'js/jquery.js' %}" type="text/javascript"></script>
    <script src="{% static 'js/bootstrap.js' %}" type="text/javascript"></script>
    <link rel="stylesheet" href="{% static 'css/bootstrap.css' %}" type="text/css">
    <link rel="stylesheet" href="{% static 'css/footer.css' %}" type="text/css">
    <link rel="stylesheet" href="{% static 'css/custom.css' %}" type="text/css">
</head>
<body>
<p>The following information has been saved, please review:</p>
<ul>
    <li>Username: <b>{{ username }}</b> </li>
    <li>Position: <b>{{ position }}</b> </li>
    <li>Department: <b>{{ department }}</b> </li>
</ul>
</body>
</html>

更新: 点击提交按钮即时发送到正确的模板页面,但在尝试写入变量的值时,我只是获取空值。使用firebug进行调试时,我发现POST数据实际上已发送到模板: 表格数据: 标题:测试 描述:测试

但是在写{{username}}时我没有得到输出。在表单的html模板中,我使用以下内容:

<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" id="username" name="username" placeholder="Username">
</div>

它应该使用一个简单的模板变量,但它不起作用。

3 个答案:

答案 0 :(得分:0)

Django现在使用基于类的视图处理特定场景的数据,它是工作的优先方式,在你的情况下,CreateView类可以为你节省很多代码:

class NewUserCreateView(CreateView):
    form_class = NewUserForm
    template_name = "yourformtemplate.html"
    success_url = yoursuccessurl

如果您需要在其中添加其他逻辑,您可以覆盖默认方法,甚至使用它们并添加其他功能/检查: http://ccbv.co.uk/projects/Django/1.6/django.views.generic.edit/CreateView/

您的示例实际上并不需要双重表单提交,因为您只是尝试重新验证数据用户提交,此数据可以在表单中验证为正常进程,您甚至可以通过覆盖在视图中添加检查而不是表单邮政方法:

def post(self, request, *args, **kwargs):
    """
    Handles POST requests, instantiating a form instance with the passed
    POST variables and then checked for validity.
    """
    form_class = self.get_form_class()
    form = self.get_form(form_class)
    if form.is_valid():
        """
        Form validation has passed, you can
        add inside here some additional checks
        """
        return self.form_valid(form)
    else:
        return self.form_invalid(form)

任何情况下这种行为也可以在Django中构建,它被命名为Form Wizard: https://docs.djangoproject.com/en/1.6/ref/contrib/formtools/form-wizard/

请记住,您无法在帖子之间传递POST数据,这就是您没有看到用户在重定向视图中提交的内容的原因,如果您想要添加表单的第二次呈现,您必须创建一个在form.is_valid()条件内呈现窗体的显示,然后将数据重新发布到另一个视图(步骤2),并在将数据插入数据库之前进行最终验证。 表单向导可以在重定向之间临时存储数据。

答案 1 :(得分:0)

你需要停下来思考这里发生的事情(不是):

        title = form.cleaned_data['username']
        description = form.cleaned_data['position']
        category = form.cleaned_data['department']
            # this is the first thing i tried, since the documentation states that you should always send a httpresponseredirect to avoid the user clicing twice on the form
            return HttpResponseRedirect("/register/user/success")

您在一个视图函数中设置了一些局部变量,然后重定向到另一个视图。它无法在第一个视图中了解局部变量。

在视图之间传递信息的一些方法:

  • 通过您重定向到的网址中的细分,在您的urls.py中以正则表达式网址格式定义,最终为第二个视图的args / kwargs,例如/register/user/3 3可以是作为arg传递给视图函数
  • 通过您重定向到的网址的查询字符串,最终会在第二个视图中显示为request.GET dict中的键,例如/register/user/success?title=whatever ...在这种情况下通常不推荐使用...因为它是通过网址轻松传递虚假数据
  • 保存到会话dict,request.session['title'] = "whatever"并在第二个视图中访问...你可以这样做,但是如果你已经将用户保存到数据库中,为什么要再次将数据保存到会话中{{3 }})

我假设您的NewUserFormUser模型的ModelForm。在这种情况下,您可能要做的是将用户保存到数据库并重定向到包含新保存用户的唯一ID的URL,因此第二个视图可以从数据库中加载该用户:

from django.shortcuts import redirect, get_object_or_404

def new_user(request):
    form = NewUserForm(request.POST or None)
    if form.is_valid():
        user = form.save()
        # note use of named view, not a url:
        return redirect('success_view', user_id=user.pk)
    return render(request, "new_user.html", {'form': form})

def success(request, user_id):
    user = get_object_or_404(User, pk=user_id)
    return render(request, "success.html", {'user': user})

并在你的urls.py中:

urlpatterns = patterns('',
    url(r'^register/user/$',
        view="myapp.views.new_user",
        name="new_user"),
    url(r'^register/user/success/(?P<user_id>\d+)?',
        view="myapp.views.success",
        name="success_view"),
)

正如@petkostas指出的那样,你可以使用Django现成的CreateView类来获得所有这些功能,只需要三行代码,这是值得推荐的。另一方面,我认为在基本的手写视图函数中查看等效函数以了解这些函数在Django中是如何工作的,这对你很有用。

答案 2 :(得分:-1)

尝试将此作为函数的返回:

return render(request, "registration_submitted.html", {'username': title})