【问题标题】:Django redirect, but pass form error contextDjango重定向,但传递表单错误上下文
【发布时间】:2016-07-22 22:08:32
【问题描述】:

我有一个非常简单的索引页面视图,用户可以从中填写一个登录弹出窗口,它会向 /login 发送一个 post 请求

def index(request):
    """Shows list of studyspaces, along with corresponding 'busyness' score"""
    context = {'study_space_list': StudySpace.objects.order_by('-avg_rating')}
    if request.user.is_authenticated():
        context['user'] = request.user
    else:
        context['login_form'] = LoginForm()
        context['user_form'] = UserForm()
        context['student_form'] = StudentForm()
    return render(request, 'spacefinder/index.html', context)

如果登录是有效,它只是重定向到索引页面,这很好用。

登录视图如下:

def user_login(request):
    form = LoginForm(request.POST)
    if request.method == 'POST' and form.is_valid():
        user = form.login(request)
        if user:
            login(request, user)
            return redirect(reverse('spacefinder:index'))
    # Load the context all over again
    context = {
        'study_space_list': StudySpace.objects.order_by('-avg_rating')
    }
    context['login_form'] = form
    context['user_form'] = UserForm()
    context['student_form'] = StudentForm()
    return render(request, 'spacefinder/index.html', context)

但是,当登录不正确时,我希望能够刷新页面并在索引模板中显示登录表单错误(在登录弹出窗口中)

我实际上可以使用上面的代码实现这一点,但我对解决方案不满意,原因如下:

  • 我必须重新手动获取上下文,例如用户/学生表格和学习空间,这违反了 DRY 原则
  • 刷新页面时,url为localhost:8000/spacefinder/login

行为截图here

我想知道是否有某种方法可以使用重定向重新加载索引页面并以某种方式从我的 login_form 传递错误,例如类似:

return redirect('spacefinder:index', {'login_form': form})

我已经研究过使用消息来传递表单验证错误,但是由于在 forms.py 中引发了验证错误,因此很难让它工作,并且我无法从 ModalForm 中获取请求实例以正确创建留言

【问题讨论】:

    标签: python django forms redirect


    【解决方案1】:

    你做错了。 考虑这些先决条件:

    1. 页面的入口点是索引视图
    2. 索引视图只能由经过身份验证的用户访问
    3. 登录视图允许GETPOST 两种方法,并且仅供匿名用户访问

    使用 Django 的原因是利用它提供的所有功能,其中包括处理上述内容(因为这是大多数页面需要的,而不仅仅是您)。

    要正确设置它,您需要像这样定义urls.py

    from django.contrib.auth.decorators import login_required
    
    urlpatterns = [
        ....
        url('^login/$', user_login, 'login'),
        url('^/$', login_required(index), 'index'),
        ....
    ]
    

    在你的settings/base.py(或settings.py,如果你没有环境区分)告诉Django如何重定向用户:

    LOGIN_URL = reverse_lazy('login')
    LOGIN_REDIRECT_URL = reverse_lazy('index')
    

    https://docs.djangoproject.com/en/1.9/ref/settings/#login-url https://docs.djangoproject.com/en/1.9/ref/settings/#login-redirect-url

    简化您的索引视图:

    def index(request):
        """Shows list of studyspaces, along with corresponding 'busyness' score"""
        context = {'study_space_list': StudySpace.objects.order_by('-avg_rating')}
        if request.user.is_authenticated():
            context['user'] = request.user
        else:
            return HttpResponseForbidden()  # prevented by Django, should never happen
        return render(request, 'spacefinder/index.html', context)
    

    让 user_login 视图传递空的登录表单:

    @require_http_methods(["GET", "POST"])
    def user_login(request):
        params = getattr(request, request.method)
        form = LoginForm(params)
        if request.method == 'POST' and form.is_valid():
            user = form.login(request)
            if user:
                login(request, user)
                return redirect(reverse('spacefinder:index'))
    
        # Load the context for new form or form with errors
        context = {
            'study_space_list': StudySpace.objects.order_by('-avg_rating')
        }
        context['login_form'] = form
        context['user_form'] = UserForm()
        context['student_form'] = StudentForm()
        return render(request, 'spacefinder/index.html', context)
    

    您尚未提供任何处理UserFormStudendForm 的代码。您还需要将其添加到 user_login 视图中 - 如果这是所有用户每次登录时都应填写的内容。否则使用不同的视图。

    allauth 这样的模块值得一看。在允许用户使用他们的电子邮件地址登录、确定电子邮件地址在系统中的唯一性等方面,他们可能会为您节省一些工作。

    【讨论】:

    • 我的页面的入口点是索引视图,但是我希望未经身份验证的用户能够看到索引页面。然后让他们能够从索引页面本身登录
    • 在这种情况下,要么将user_loginindex 的代码移到一个视图中,要么通过AJAX POST 调用user_login 并仅将登录部分替换为返回的HTML(您可以使用仅返回表单 HTML 的部分模板,包括错误)。
    • 我认为结合登录和索引视图可能是最好的解决方案。非常感谢您的帮助!
    猜你喜欢
    • 2022-01-22
    • 2017-11-15
    • 2022-01-25
    • 2020-02-11
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    相关资源
    最近更新 更多