【问题标题】:proper way to use django render_to_response in this situation?在这种情况下使用 django render_to_response 的正确方法?
【发布时间】:2013-07-28 11:50:06
【问题描述】:

基本上,在我的 index.html 模板中,我希望将登录和注册表单放在同一个(两者都有 csrf_token)上。这是我的看法。

def index(request):
    c = {}
    c.update(csrf(request))
    if request.method == 'POST':
        form = MyRegistrationForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/accounts/register_success')

    args = {}
    args.update(csrf(request))

    args['form'] = MyRegistrationForm()

    return render_to_response('index.html', {c, form: args})

问题在于 render_to_response 语句。之前,我将索引视图作为两个不同的视图。

    c = {}
    c.update(csrf(request))
    return render_to_response('index.html', c)

是登录的返回语句,

    if request.method == 'POST':
        form = MyRegistrationForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/accounts/register_success')

    args = {}
    args.update(csrf(request))

    args['form'] = MyRegistrationForm()

    return render_to_response('register.html', args)

是注册表单的返回声明。 (注册表单和 index.html 登录表单之前在两个不同的模板中。我正在尝试将它们放在一个模板中。

这是我的 index.html 模板(两个表单都在同一个模板中)。

<form action="/accounts/auth/" method="post">{% csrf_token %}
    <label for="username">User name:</label>
    <input type="text" name="username" value="" id="username">
    <label for="password">Password:</label>
    <input type="password" name="password" value="" id="password">

    <input type="submit" value="login" />

</form>
<h2>Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
    {{form}}

    <input type="submit" value="Register" />

</form>

【问题讨论】:

    标签: django render


    【解决方案1】:

    你没有解释你的问题是什么,但我发现一件大事立即看起来不对。

    render_to_response 需要一个字典作为其上下文参数。您提供的值 {c, form: args} 不是字典。

    在足够新的 Django 版本上,您通常希望使用 render 而不是 render_to_response。它完成了render_to_response 所做的一切,并且还使用了RequestContext 对象,以便上下文处理器正常工作。这对于 csrf 处理特别有用。正如docs 所说:

    在相应的视图函数中,确保正在使用“django.core.context_processors.csrf”上下文处理器。通常,这可以通过以下两种方式之一完成:

    1. 使用 RequestContext,它始终使用“django.core.context_processors.csrf”(无论您的 TEMPLATE_CONTEXT_PROCESSORS 设置如何)。

    2. 手动导入并使用处理器生成 CSRF 令牌并将其添加到模板上下文中。

    总的来说,我会将您的观点改写为:

    def index(request):
        if request.method == 'POST':
            form = MyRegistrationForm(request.POST)
            if form.is_valid():
                form.save()
                return HttpResponseRedirect('/accounts/register_success')
        else:
            form = MyRegistrationForm()
    
        return render(request, 'index.html', {form: form})
    

    只是为了演示如何在没有RequestContext 的情况下执行此操作:

    def index(request):
        c = {}
        c.update(csrf(request))
        if request.method == 'POST':
            form = MyRegistrationForm(request.POST)
            if form.is_valid():
                form.save()
                return HttpResponseRedirect('/accounts/register_success')
        else:
            form = MyRegistrationForm()
        c['form'] = form
        return render_to_response('register.html', c)
    

    重点是将表单和 csrf 令牌都放入字典中。

    使用redirect 快捷方式和视图名称而不是固定 URL 来确定重定向目标通常是一个好习惯。

    【讨论】:

    • 我的问题是,早些时候我在不同的视图/模板中注册和登录时,我在登录视图中使用了 return render_to_response('index.html', c) 并 return render_to_response('register.html ', args) 在注册视图中。现在我将它们两个视图放在一起,我将如何合并两个 render_to_response 语句?
    • 嗯好吧,那么返回redirect('viewname')?好的,谢谢,我会记住的
    • 另外,当使用@csrf_protect 时,我不是必须在视图中有c={} 然后渲染c 吗?在你重做的视图中,你没有渲染 c 对吗?
    • 还有一件事,早些时候当我的登录表单和模板与注册表单和模板分开时,登录视图是 c = {} c.update(csrf(request)) return render_to_response(' index.html', c)... 我什至需要那个视图吗?我渲染c没用吗?因为在您的回答中,您并没有真正为登录表单呈现 c。
    • render 生成的RequestContextrender_to_response 不同,它总是通过上下文处理器,在必要时添加令牌。我将添加更多有关它的信息。
    猜你喜欢
    • 1970-01-01
    • 2018-09-22
    • 2011-03-26
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    • 2020-08-06
    • 2022-01-11
    • 1970-01-01
    相关资源
    最近更新 更多