如何使用requests访问带@login_required装饰器的Django视图?
问题:访问带@login_required的Django API视图失败,触发反向解析错误
尝试用requests库访问带有@login_required装饰器的Django视图,采用HTTPBasicAuth认证,但遇到以下错误:
django.urls.exceptions.NoReverseMatch: Reverse for 'login' not found. 'login' is not a valid view function or pattern name. [11/Jan/2023 04:24:11] "GET /api/users/ HTTP/1.1" 500 71617
相关代码
视图代码
@login_required def user_list(request): users = User.objects.filter(is_active=True) serializer = ContactSerializer(users) return Response(serializer.data)
URL配置
path('', views.dashboard, name='dashboard'), path('', include('django.contrib.auth.urls')) path('users/', views.user_list, name='user_list')
项目设置
LOGIN_REDIRECT_URL = 'dashboard' LOGIN_URL = 'login' LOGOUT_URL = 'logout'
尝试的访问代码
import requests from requests.auth import HTTPBasicAuth # 原代码可能遗漏该导入 response = requests.get('http://127.0.0.1:8000/api/users/', auth = HTTPBasicAuth('user', 'pass'))
问题原因
- URL配置顺序&语法错误:
include('django.contrib.auth.urls')的路由和dashboard的路由都是空字符串,且前者排在后面,Django从上到下匹配路由时会优先命中dashboard,导致auth的登录路由未被加载;同时第二行末尾缺少逗号,属于语法错误。 - API视图用错认证装饰器:
@login_required是针对普通Web视图的,会触发页面重定向到登录页,但API场景不需要页面跳转,该装饰器不适用。 - HTTPBasicAuth不兼容Session认证:
@login_required依赖Django的Session机制,而requests的HTTPBasicAuth仅在请求头传递认证信息,不会自动建立登录Session。
解决步骤
1. 修复URL配置
调整路由顺序并添加前缀,确保auth路由能被正确加载,同时修正语法错误:
path('', views.dashboard, name='dashboard'), path('accounts/', include('django.contrib.auth.urls')), # 添加前缀+补上逗号 path('users/', views.user_list, name='user_list')
2. 为API视图改用DRF认证方案(推荐)
如果是API场景,优先使用Django REST Framework的认证体系:
方案A:结合Session&Basic认证
from rest_framework.decorators import api_view, authentication_classes, permission_classes from rest_framework.authentication import SessionAuthentication, BasicAuthentication from rest_framework.permissions import IsAuthenticated @api_view(['GET']) @authentication_classes([SessionAuthentication, BasicAuthentication]) @permission_classes([IsAuthenticated]) def user_list(request): users = User.objects.filter(is_active=True) serializer = ContactSerializer(users) return Response(serializer.data)
方案B:Token认证
- 先在
settings.py配置Token认证:
INSTALLED_APPS = [ # 其他应用 'rest_framework.authtoken', ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ], }
- 生成用户Token:执行命令
python manage.py drf_create_token <用户名> - 用requests携带Token访问:
import requests response = requests.get('http://127.0.0.1:8000/api/users/', headers={'Authorization': 'Token <你的用户Token>'})
3. 若坚持用@login_required(不推荐API场景)
需要先通过requests模拟登录获取Session,再访问目标视图:
import requests # 初始化会话并获取CSRF Token session = requests.Session() login_page = session.get('http://127.0.0.1:8000/accounts/login/') csrf_token = login_page.cookies.get('csrftoken') # 提交登录请求 login_data = { 'username': 'user', 'password': 'pass', 'csrfmiddlewaretoken': csrf_token } session.post('http://127.0.0.1:8000/accounts/login/', data=login_data) # 访问用户列表视图 response = session.get('http://127.0.0.1:8000/api/users/')
内容的提问来源于stack exchange,提问作者chez93
相关产品推荐
相关产品推荐

