python - Django 重定向,但传递表单错误上下文

标签 python django forms redirect

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

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)

如果登录名有效,它会简单地重定向到索引页面,这很好用。

登录 View 如下所示:

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

我想知道是否有某种方法可以使用重定向来重新加载索引页面并以某种方式传递来 self 的 login_form 的错误,例如像这样的东西:

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

我已经研究过使用消息来传递表单验证错误,但由于验证错误被抛入到 forms.py 中,所以很难使它正常工作,而且我无法从 ModalForm 中获取请求实例以正确创建留言

最佳答案

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

  1. 您页面的入口点是索引 View
  2. 索引 View 只能由经过身份验证的用户访问
  3. 登录 View 允许两种方法 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

简化您的索引 View :

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 View 传递空的登录表单:

@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 View - 如果这是所有用户每次登录时都应填写的内容。否则使用不同的 View 。

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

关于python - Django 重定向,但传递表单错误上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36384491/

相关文章:

python - Debian Python 2.5 包括来自 AlchemyAPI 的模块

python - Heroku 与 Django 的使用

python - 禁止 save() 以防止由于未保存的相关对象导致数据丢失

python - 序列化程序被多次调用 django python

jquery - 使用 Jquery 验证时无法提交表单

python - 如何处理具有多个蓝图的 flask 中的登录?

python - 如何让GtkMenuToolButton在发出 'clicked'信号时打开相同的菜单?

使用 spynner 时出现 Python 6 库错误

python - Django 表单对象没有属性问题

php - 安全的 PHP 文件上传脚本