【问题标题】:Render without passing request在不通过请求的情况下渲染
【发布时间】:2014-09-21 01:42:38
【问题描述】:

Django 新手,我在这方面遇到了一些麻烦。

我有一个注册表单,它会在成功提交后在数据库中创建行。

提交后,我想将用户重定向到登录表单(这需要我将表单作为 render() 的参数传递),并将状态“REGISTRATION_SUCCESSFUL”传递为也是一个参数。

return render(request, 'login.html', {
    'form': login_form(), 
    'status': 'REGISTRATION_SUCCESSFUL'
})

根据状态,我的模板会显示一条消息,指示注册成功。

在您尝试刷新登录页面之前一切正常,它会尝试再次提交注册表单(我想是因为请求已转发到登录页面)。

我尝试过的所有方法都涉及转发请求,这被证明是一个问题。帮助?

提前致谢!

【问题讨论】:

    标签: python django django-forms django-templates


    【解决方案1】:

    表单提交后,不要使用渲染,而是使用HTTPResponseRedirect。成功处理 POST 数据后,始终返回 HttpResponseRedirect。如果用户点击“后退”按钮,这可以防止数据被发布两次。

    您在这里面临的问题是 HTTPResponseRedirect 不允许您传递状态为 REGISTRATION_SUCCESSFUL 的上下文。

    根据状态,我的模板会显示一条消息,表明注册成功。

    这是您可以使用Django's messages framework 的地方。在HTTPResponseRedirect 之前,您可以执行以下操作:

    from django.contrib import messages
    from django.core.urlresolvers import reverse
    from django.http import HttpResponseRedirect
    from django.shortcuts import render
    from .forms import RegistrationForm
    
    def registration(request):
        if request.method == 'POST':
            form = RegistrationForm(request.POST)
            if form.is_valid():
                # ... do something special here if needed
                messages.add_message(request, messages.INFO, 'Registration was successful!')
                return HttpResponseRedirect(reverse('login_page'))
        else:
            form = RegistrationForm()
            return render(request, 'registration.html', {'form': form})
    

    现在在您的“登录页面”中,您可以显示消息。仅供参考 - 消息是基于每个会话的,因此“注册成功”消息只会显示给您重定向的用户:

    login_page.html:(来自messages documentation的示例)

    {% if messages %}
        <ul class="messages">
            {% for message in messages %}
                <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}    </li>
            {% endfor %}
        </ul>
    {% endif %}
    
    <form method="post">{% csrf_token %}
        {{ form }} {# Your login form #}
    </form>
    

    在此示例中,您添加的任何消息都将显示在您的登录表单上方。如果还有“注册无效”等其他信息,就会显示出来。

    请务必将以下内容添加到您的settings.INSTALLED_APPSEnable the Django Messages Framework

    INSTALLED_APPS = (
        ...
        'django.contrib.messages',
    )
    

    您的settings.MIDDLEWARE_CLASSES 必须包含:

    MIDDLEWARE_CLASSES = (
        ...
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
    )
    

    您的settings.TEMPLATE_CONTEXT_PROCESSORS 必须包含:

    TEMPLATE_CONTEXT_PROCESSORS = (
        ...
        'django.contrib.messages.context_processors.messages',
    )
    

    【讨论】:

    • 做到了!太感谢了。对于任何想要实现上述内容的人,请确保您的 settings.py 文件配置正确(有这个问题)。
    • @DarylChan - 我根据您的 settings.py 评论更新了我的答案,供未来的读者参考。
    【解决方案2】:

    注册成功后,您可能需要考虑redirect,这是成功发帖后的常见做法。

    Django 提供了重定向的捷径。

    return redirect('some-view-name', foo='bar')
    
    return redirect('/some/url/')
    

    对于您的情况,您可以考虑:

    kwargs={'status': 'REGISTRATION_SUCCESSFUL' }
    
    return redirect('login-view', **kwargs)
    

    【讨论】:

    • 澄清一下,如果他的 URL 配置准备好处理视图的“状态”参数,这可能会起作用。但是,我不喜欢这种方法,因为它会使 URL 变得混乱。它会显示example.com/login/REGISTRATION_SUCCESSFUL
    • @MichaelB:不,不会。您只是传递可以被拉入正在重定向到的 login.html 模板的参数
    • 为了确保我没有错误地阅读文档,我测试并得到了我预期的错误:Reverse for 'test_redirect_to' with arguments '()' and keyword arguments '{'状态': 'REGISTRATION_SUCCESSFUL'}' 未找到。根据redirect documentation,参数可以是模型、视图名称(带有“状态”等参数)或绝对URL。
    • @MichaelB:我同意你的说法。为什么渲染不起作用?当您在登录页面时,为什么刷新再次发布注册表单。由于Http是无状态的,所以登录表单渲染时,注册的post表单数据应该没有?
    • @MichaelB:在问题中,Daryl 声称刷新登录页面会重新发布注册,但没有点击我想了解的返回按钮
    【解决方案3】:
    from django.contrib import messages
    from django.http import HttpResponseRedirect
    
    
    if form1.is_valid():
                registration = form1.save(commit=False)
                registration.save()            
                messages.success(request, 'Your message here.')
                return HttpResponseRedirect('/login/')
    

    在模板中。 在要显示消息的 div 中

    {% block message %}
    
       {% include "includes/messages.html"%}
    {% endblock %}
    

    然后在include文件夹中创建message.html文件

    <div id="messages">
        {% for message in messages %}
            <div class="alert alert-{{message.tags }} alert-dismissable">
                  <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
                    {{ message }}
            </div>      
    
        {% endfor %}
    </div>
    

    完成后,您的页面将重定向到登录页面,并在该页面上显示消息。

    【讨论】:

      猜你喜欢
      • 2018-09-19
      • 2018-02-13
      • 2021-11-14
      • 2019-06-14
      • 1970-01-01
      • 2019-09-06
      • 2012-08-05
      • 1970-01-01
      • 2021-05-14
      相关资源
      最近更新 更多