Django:ajax 调用时 login_required
Posted
技术标签:
【中文标题】Django:ajax 调用时 login_required【英文标题】:Django: login_required on ajax call 【发布时间】:2014-04-07 10:22:40 【问题描述】:我正在尝试对 ajax 帖子上的用户进行身份验证,但不起作用。这是我所做的
settings.py
LOGIN_URL = '/accounts/login/'
LOGIN_REDIRECT_URL = '/'
模板
<script>
$('.btn-request').click(function()
var button = this;
$.ajax(
type: "POST",
url: "% url 'like' %",
data: 'tutorial_id': $(this).attr('name'), 'csrfmiddlewaretoken': 'csrf_token',
dataType: "json",
success: function(json)
toastr.success(json.message);
,
error: function(rs, e)
alert(rs.responseText);
);
)
</script>
urls.py
url(r'^like/$', 'apps.quotation.views.like', name='like'),
views.py - 尝试 1
@login_required
def like(request):
vars =
if request.method == 'POST':
response_dict =
if not something:
response_dict.update('message': "Requested" )
else:
response_dict.update('message': "You have already requested" )
return HttpResponse(simplejson.dumps(response_dict),
mimetype='application/javascript')
views.py - 尝试 2
def like(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login')
else:
vars =
if request.method == 'POST':
response_dict =
if not something:
response_dict.update('message': "Requested" )
else:
response_dict.update('message': "You have already requested" )
return HttpResponse(simplejson.dumps(response_dict),
mimetype='application/javascript')
运行服务器日志
[05/Mar/2014 05:19:16] "POST /like/ HTTP/1.1" 302 0
[05/Mar/2014 05:19:16] "GET /accounts/login/?next=/like/ HTTP/1.1" 200 5610
我错过了什么?
【问题讨论】:
您是否已登录以管理管理站点? views.py 尝试 2:“如果不是 request.user.is_authenticated():return...” 这与我使用的代码相同,为什么不在模板中显示用户? request.user 以确保您没有登录 我没有登录管理员。 request.user 在模板中显示了 AnonymousUser,我猜这意味着用户未通过身份验证? 是的,用户未经过身份验证,但您似乎在某个地方管理未经身份验证的用户。尝试类似“if request.user == 'AnonymousUser': return...” 【参考方案1】:我不确定这是否是一个优雅的解决方案,但我按照Priyank Patel 的建议让它工作
<script>
$('.btn-request').click(function()
var button = this;
$.ajax(
type: "POST",
url: "% url 'like' %",
data: 'tutorial_id': $(this).attr('name'), 'csrfmiddlewaretoken': 'csrf_token',
dataType: "json",
success: function(json)
if(json.not_authenticated)
window.location.replace("/accounts/login");
else
toastr.success(json.message);
,
error: function(rs, e)
alert(rs.responseText);
);
)
</script>
views.py
def like(request):
response_dict =
if request.user.is_authenticated():
if request.method == 'POST':
if not something:
response_dict.update('message': "Requested" )
else:
response_dict.update('message': "You have already requested" )
return HttpResponse(simplejson.dumps(response_dict),
mimetype='application/javascript')
else:
response_dict.update('message': "Login please",'not_authenticated':True )
return HttpResponse(simplejson.dumps(response_dict),
mimetype='application/javascript')
【讨论】:
【参考方案2】:而不是:
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login')
返回 json 响应:
if request.user.is_authenticated():
## write your code...
jsonr = json.dumps( 'authenticated': True )
return HttpResponse(jsonr, mimetype='application/json')
else:
jsonr = json.dumps( 'authenticated': False )
return HttpResponse(jsonr, mimetype='application/json')
并且在您的 ajax 成功响应中,如果未通过身份验证,则使用 windows.location
重定向到登录。
或你可以写装饰器: Django authentication and Ajax - URLs that require login
【讨论】:
is_authenticated 现在是布尔运算符.. 对于 Django 2.0【参考方案3】:当我想检查在进行 Ajax 调用时用户是否已登录,这是我使用的:
from functools import wraps
from django.core.exceptions import PermissionDenied
def ajax_login_required(view):
@wraps(view)
def wrapper(request, *args, **kwargs):
if not request.user.is_authenticated():
raise PermissionDenied
return view(request, *args, **kwargs)
return wrapper
raise PermissionDenied
将导致向客户端返回 403 状态代码。否则,如果您使用 @login_required
装饰器或手动执行对表单的重定向,那么 Ajax 调用视为响应的内容对人类有意义,但对 Ajax 调用没有意义。
【讨论】:
我认为如果问题是用户没有登录而不是他们没有适当的权限,他们应该得到一个 401 错误而不是 403。 OP 不是关于要返回的状态代码的表达式混淆,而是当请求是 AJAX 时使用什么机制来返回合理的东西。如果开发人员需要,我的答案可以很容易地适应给 401 而不是 403。当用户未登录时,必需肯定不是真的。(例如,参见this answer。) @Louis 401 与 403 链接的要点不是:401 = 未经过身份验证(即登录)并且; 403 = 未授权(即已登录但没有正确的权限)? @CpILL 这根本不是我链接到的答案的要点。那里的许多其他答案都对您提到的 401 和 403 进行了区分,但我链接到的答案特别指出这不是正确的区分。 401 用于当您的身份验证机制使用Authorization
标头时。我部署的所有 Django 服务器都没有使用这种机制。
您的第一个报价结束得太早了。以下是相关部分:“服务器正在请求客户端通过 HTTP 身份验证登录并已发送回复标头以启动流程”我已将重要部分加粗。看,401 不是您在任何时候由于用户未登录而无法完成请求时发送的响应。仅在您希望用户使用“HTTP 身份验证”时发送它。而且“HTTP 身份验证”不是一个通用术语,而是一个指代 HTTP 标头的特定用途的术语。默认情况下,django不使用这个方法,所以401是不合适的。以上是关于Django:ajax 调用时 login_required的主要内容,如果未能解决你的问题,请参考以下文章
jQuery AJAX POST 在第一次调用时跳过 Django CSRF 令牌标头
当前路径具有子目录或 url 参数时,使用 AJAX 调用视图函数不起作用(Django)