gpt4 book ai didi

django - 通过 login_required 装饰器转发 POST 参数的建议方法?

转载 作者:行者123 更新时间:2023-12-04 07:09:44 24 4
gpt4 key购买 nike

我目前遇到的问题是,当我在我的任何 View 上使用来自 django.contrib.auth.decorators 的 login_required 装饰器时,只要装饰器重定向(到登录页面)并返回,我的 POST 参数就不会到达 protected View 再次进入 protected View 。关于如何解决这个问题的建议(最好保持 login_required 装饰器和 POST 方法的便利)感谢!

This page似乎是关于此事的有争议的 Django 票。尽管错误/增强功能是根据模板与 View 逻辑来构建的,而不是仅仅使 View 可以访问参数,这是我的问题。

最佳答案

我使用我认为可以接受的 session 开发了以下解决方案。处理重定向和替换 View 是棘手的,这种方法似乎是在获得所需功能的同时不摆弄框架和不对抗 HTTP 协议(protocol)的最佳平衡。此方法的不利方面是每个 protected View 检查 session 变量所需的额外工作。

  • 创建一个自定义装饰器(login_required2,如下),如果用户通过身份验证,则返回请求的 View ,否则返回项目的登录 View 。
  • 登录 View :
  • 存储原始POST session 变量中的参数。
  • 存储原始HTTP_REFERER在 session 变量中
  • 如果用户正确验证,则返回与请求路径对应的 View (请求路径在整个登录过程中保持相同,并且与用户最初通过登录 View 时请求的路径相同。)
  • 因此,任何 protected View 都必须在使用请求的 POST 之前检查 session 变量。或 META['HTTP_REFERER']

  • 代码如下:
    def login_view(request):    
    from django.conf import settings
    from django.core.urlresolvers import resolve

    USERNAME_FIELD_KEY = 'username'
    PASSWORD_FIELD_KEY = 'password'

    message = '' #A message to display to the user
    error_message = '' #An error message to display to the user

    #If the request's path is not the login URL, the user did not explicitly request
    # the login page and we assume this view is protecting another.
    protecting_a_view = request.path != settings.LOGIN_URL

    post_params_present = bool(request.POST)

    #Any POST with username and password is considered a login attempt, regardless off what other POST parameters there may be
    login_attempt = request.POST and request.POST.has_key(USERNAME_FIELD_KEY) and request.POST.has_key(PASSWORD_FIELD_KEY)

    if protecting_a_view:
    message = 'You must login for access.'
    if not request.session.has_key(ACTUAL_REFERER_KEY):
    #Store the HTTP_REFERER if not already
    request.session[ACTUAL_REFERER_KEY] = request.META.get(HTTP_REFERER_KEY)

    if protecting_a_view and post_params_present and not login_attempt:
    #Store the POST parameters for the protected view
    request.session[FORWARDED_POST_PARAMS_KEY] = request.POST

    if login_attempt:
    form = LoginForm(request.POST)
    if form.is_valid():
    username = form.cleaned_data[USERNAME_FIELD_KEY]
    password = form.cleaned_data[PASSWORD_FIELD_KEY]
    user = auth.authenticate(username=username, password=password)
    if user is not None:
    if user.is_active:
    auth.login(request, user)
    if protecting_a_view:
    actual_view, actual_args, actual_kwargs = resolve(request.path) #request.path refers to the protected view
    return actual_view(request, *actual_args, **actual_kwargs)
    else:
    HttpResponseRedirect('/')
    else:
    message = 'That account is inactive.'
    else:
    error_message = 'That username or password is incorrect.'
    else:
    form = LoginForm()

    context_dict = {
    'form': form,
    'message': message,
    'error_message': error_message,
    }
    return render_to_response2('my_app/login.html', context_dict)

    @login_required2
    def protected_view(request):
    post_params = {}

    if request.POST:
    post_params = request.POST
    elif request.session.has_key(FORWARDED_POST_PARAMS_KEY):
    post_params = request.session[FORWARDED_POST_PARAMS_KEY]
    del request.session[FORWARDED_POST_PARAMS_KEY]
    if post_params:
    #Process post_params as if it were request.POST here:
    pass

    #assuming this view ends with a redirect. Otherwise could render view normally
    if request.session.has_key(ACTUAL_REFERER_KEY):
    redirect_location = request.session.get(ACTUAL_REFERER_KEY)
    elif request.META.get(HTTP_REFERER_KEY) != request.path:
    redirect_location = request.META.get(HTTP_REFERER_KEY)
    else:
    redirect_location = ROOT_PATH
    return HttpResponseRedirect(redirect_location)

    def login_required2(view_func):
    """
    A decorator that checks if the request has an authenticated user.
    If so it passes the request to the view.
    Otherwise, it passes the request to the login view, which is responsible
    for recognizing that the request was originally for another page and forwarding
    state along (GET, POST).

    See django.contrib.auth.decorators for how Django's auth decorators mesh
    using _CheckLogin. This decorator bypasses that for my ease of creation.
    """
    def login_required_decoration(request, *args, **kwargs):
    if request.user.is_authenticated():
    return view_func(request, *args, **kwargs)
    else:
    from django.conf import settings
    from django.core.urlresolvers import resolve

    login_url = settings.LOGIN_URL
    login_view, login_args, login_kwargs = resolve(login_url)
    #Here the user gets a login view instad of the view they requested
    return login_view(request, *login_args, **login_kwargs)
    return login_required_decoration

    关于django - 通过 login_required 装饰器转发 POST 参数的建议方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/563819/

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