gpt4 book ai didi

python - 指定 Django login_required 装饰器传递给登录 View 的 `next` url

转载 作者:太空狗 更新时间:2023-10-30 02:57:18 25 4
gpt4 key购买 nike

来自 the Django documentation我知道当您在 View 上使用 @login_required 装饰器时,如果用户未登录,Django 将:

redirect to settings.LOGIN_URL, passing the current absolute path in the query string.

因此,如果从 url /foo/bar/ 调用装饰 View ,它们将被重定向到:

/login/?next=/foo/bar/ 

我想知道是否有一种好方法可以为特定 View 指定 'next' 路径,而不是使用默认值或在 settings.LOGIN_REDIRECT_URL 中对其进行硬编码。

我的网站目前的设置方式(我不确定这是否是最好的方式)我有一个项目详细信息页面,当用户尝试对项目进行操作时(即 POST 表单数据并更改数据库中的项目记录)但他们没有登录,它将他们重定向到登录页面。

我的问题是为 next 参数传递的路径是表单 POSTing 操作的路径,我希望用户被重定向到他们之前所在的项目详细信息页面。有没有一种方法可以指定将哪个 URL 作为 next 参数传递,而不是使用默认值或在 settings.py 中定义它?

最佳答案

此限制仅适用于 Django 的 /admin/ 部分。您可以编写自己的登录 View ,重定向到您想要的任何地方(本文底部的示例)。

当前的 admin 功能似乎是围绕这样的想法编写的,即管理员应该始终返回到在被重定向到登录页面之前查看过的输入 url。

如我所见,要更改管理员的这种行为,这些是您的选择。

自定义 login_required 装饰器

要更改默认行为,请将 next 关键字参数添加到 login_required 功能。这将需要重写 django.contrib.auth.decorators 中的 login_required 函数和 user_passes_test 辅助函数。根据原始代码,它可能类似于:

def user_passes_test(test_func, next=None, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
Decorator for views that checks that the user passes the given test,
redirecting to the log-in page if necessary. The test should be a callable
that takes the user object and returns True if the user passes.
"""

def decorator(view_func):
@wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request, *args, **kwargs):
if test_func(request.user):
return view_func(request, *args, **kwargs)
path = request.build_absolute_uri()
resolved_login_url = resolve_url(login_url or settings.LOGIN_URL)
# If the login url is the same scheme and net location then just
# use the path as the "next" url.
login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
current_scheme, current_netloc = urlparse(path)[:2]
if ((not login_scheme or login_scheme == current_scheme) and
(not login_netloc or login_netloc == current_netloc)):
path = request.get_full_path()
resolved_next_url = resolve_url(next or path)
from django.contrib.auth.views import redirect_to_login
return redirect_to_login(
resolved_next_url, resolved_login_url, redirect_field_name)
return _wrapped_view
return decorator


def login_required(function=None, next=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
"""
Decorator for views that checks that the user is logged in, redirecting
to the log-in page if necessary.
"""
actual_decorator = user_passes_test(
lambda u: u.is_authenticated,
next=next
login_url=login_url,
redirect_field_name=redirect_field_name,
)
if function:
return actual_decorator(function)
return actual_decorator

在上面的代码中,我添加了关键字 args next 并添加了下一个 url 解析。 Django 的 original login_required can be found here .

这将使您能够:

@login_required(next='app:view')
def profile(request):
....

手动下一个查询参数

或者,您可以在已设置下一个参数的情况下手动创建登录 URL,但这似乎不适用于您的情况。

<a href="/login/?next=/app/view/" />Login</a>

创建一个替换下一个参数的中间件

如果您打算重定向到单个 url - 也许也可以重定向到一个 url - 那么中间件可能是一个选项。确保将此中间件放在 AuthenticationMiddleware 之前。中间件看起来像这样:

class LoginNextMiddleware(object):
redirect_url = '/app/view/'

def process_request(self, request):
next_url = request.GET.get('next', None)
if next_url is not None and next_url != self.redirect_url:
params = dict(request.GET.copy())
del params['next']
params['next'] = self.redirect_url
return redirect(request.path + '?' + urlencode(params))

编写自定义登录 View

最后,如果您想要灵 active ,编写自定义登录 View 是可行的方法。这看起来像:

def login_user(request):
logout(request)
username = password = ''
if request.POST:
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None and user.is_active:
login(request, user)
return HttpResponseRedirect(reverse('app:view'))
return render_to_response('login.html', context_instance=RequestContext(request))

并且需要自定义表单,例如:

<form action="{{ request.get_full_path }}" method="post">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.get_full_path }}" />
<input type="text" autofocus name="username" />
<input type="password" name="password" />
<button type="submit">Log in</button>
</form>

关于python - 指定 Django login_required 装饰器传递给登录 View 的 `next` url,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37598155/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com