Django多用户应用登录异常:admin登录跳转至student登录表单
Django多角色登录异常:Admin登录重定向到Student登录表单
我开发的Django应用包含teacher、student和admin三种用户角色,teacher和student角色登录功能正常,但使用admin账号登录时,页面会重定向到student的登录表单。怀疑问题出在urls.py配置或next参数设置上,不知道该怎么排查。
相关代码文件
admin views.py
@login_required @admin_required def profile(request): if request.method == 'POST': u_form = UserUpdateForm(request.POST, instance=request.user) p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile) if u_form.is_valid() and p_form.is_valid(): u_form.save() p_form.save() messages.success(request, f'Your account has been updated!') return redirect('profile') else: u_form = UserUpdateForm(instance=request.user) p_form = ProfileUpdateForm(instance=request.user.profile) context = { 'u_form': u_form, 'p_form': p_form } return render(request, 'users/profile.html', context)
main urls.py
urlpatterns = [ path('', classroom.home, name='home'), path('students/', include(([ path('', students.QuizListView.as_view(), name='quiz_list'), path('interests/', students.StudentInterestsView.as_view(), name='student_interests'), path('taken/', students.TakenQuizListView.as_view(), name='taken_quiz_list'), path('quiz/<int:pk>/', students.take_quiz, name='take_quiz'), ], 'classroom'), namespace='students')), path('teachers/', include(([ path('', teachers.QuizListView.as_view(), name='quiz_change_list'), path('quiz/add/', teachers.QuizCreateView.as_view(), name='quiz_add'), path('quiz/<int:pk>/', teachers.QuizUpdateView.as_view(), name='quiz_change'), path('quiz/<int:pk>/delete/', teachers.QuizDeleteView.as_view(), name='quiz_delete'), path('quiz/<int:pk>/results/', teachers.QuizResultsView.as_view(), name='quiz_results'), path('quiz/<int:pk>/question/add/', teachers.question_add, name='question_add'), path('quiz/<int:quiz_pk>/question/<int:question_pk>/', teachers.question_change, name='question_change'), path('quiz/<int:quiz_pk>/question/<int:question_pk>/delete/', teachers.QuestionDeleteView.as_view(), name='question_delete'), ], 'classroom'), namespace='teachers')), path('admins/', include(([ path('', admins.profile, name='profile'), ], 'classroom'), namespace='admins')), ]
login urls.py
urlpatterns = [ path('', include('classroom.urls')), path('accounts/', include('django.contrib.auth.urls')), path('accounts/signup/', classroom.SignUpView.as_view(), name='signup'), path('accounts/signup/student/', students.StudentSignUpView.as_view(), name='student_signup'), path('accounts/signup/teacher/', teachers.TeacherSignUpView.as_view(), name='teacher_signup'), path('accounts/signup/admin/', admins.register, name='register'), ]
signup form template
{% extends 'base.html' %} {% load crispy_forms_tags %} {% block content %} <div class="row"> <div class="col-md-8 col-sm-10 col-12"> <h2>Sign up as a {{ user_type }}</h2> <form method="post" novalidate> {% csrf_token %} <input type="hidden" name="next" value="{{ next }}"> {{ form|crispy }} <button type="submit" class="btn btn-success">Sign up</button> </form> </div> </div> {% endblock %}
admin form template
{% extends "base.html" %} {% load crispy_forms_tags %} {% block content %} <div class="content-section"> <form method="POST"> {% csrf_token %} <fieldset class="form-group"> <input type="hidden" name="next" value="{{ next }}"> <legend class="border-bottom mb-4">Join Today</legend> {{ form|crispy }} </fieldset> <div class="form-group"> <button class="btn btn-outline-info" type="submit">Sign Up</button> </div> </form> <div class="border-top pt-3"> <small class="text-muted"> Already Have An Account? <a class="ml-2" href="{% url 'login' %}">Sign In</a> </small> </div> </div> {% endblock content %}
排查与解决步骤
1. 检查全局登录重定向配置
先看settings.py里的LOGIN_REDIRECT_URL,如果这个值直接指向了student的页面(比如students:quiz_list),所有角色登录后都会跳去student页面。需要改成动态判断角色的视图,或者配置为空,让登录视图自行处理跳转。
2. 验证admin_required装饰器逻辑
你的profile视图用了@admin_required装饰器,检查这个装饰器的代码:
- 如果装饰器在用户未登录时直接返回
redirect('login'),而默认的login视图和student登录逻辑绑定,就会出现重定向错误。应该让装饰器重定向时带上next参数,比如redirect('login') + f'?next={request.path}',确保登录后能回到admin的目标页面。
3. 自定义登录视图实现角色分流
Django自带的登录视图不区分角色,需要自定义登录视图,在登录成功后根据用户角色跳转:
from django.contrib.auth.views import LoginView from django.urls import reverse class CustomLoginView(LoginView): def get_success_url(self): # 假设用户模型有is_admin、is_teacher、is_student字段 if self.request.user.is_admin: return reverse('admins:profile') elif self.request.user.is_teacher: return reverse('teachers:quiz_change_list') elif self.request.user.is_student: return reverse('students:quiz_list') return super().get_success_url()
然后在login urls.py里替换默认登录路径:
path('accounts/login/', CustomLoginView.as_view(), name='login'),
4. 确认next参数传递有效性
访问/admins/时,未登录状态下应该被重定向到/accounts/login/?next=/admins/。检查浏览器地址栏是否有这个next参数,如果没有,说明装饰器或中间件拦截了参数传递;如果有但登录后没跳对,说明登录视图没正确处理next参数。
5. 检查URL命名空间配置
确认admins:profile的命名空间能正确反向解析,在main urls.py中,include的命名空间namespace='admins'和应用名称是否匹配,避免反向解析失败导致跳转到默认页面。
内容的提问来源于stack exchange,提问作者mdaw11
相关产品推荐
相关产品推荐

