将视图参数传递给装饰器并重定向到登录视图

时间:2015-04-21 03:13:45

标签: django view decorator

这是我的管理视图,我需要一个装饰器代替“event_session_check”,但我不知道如何将“event_key”传递给装饰器,所以我写了“event_session_check”......

“event_session_required”将验证EventSet模型中的ID和密码而不是auth.User,请帮帮我...

"""
def event_session_required():
    def _session_required(view_func):
        @wraps(view_func)
        def __session_required(request, *args, **kwargs):
            next = request.get_full_path()
            event_key = kwargs.pop('event_key', '')
            session_key = 'event_%s' % event_key
            print session_key
            login_path = reverse('event-manage-login', args=[event_key])
            redirect_url = login_path + '?next=' + next
            try:
                session = request.session.get(session_key)
                if session is None:
                    raise ValueError('Cannot use None at session value')
            except KeyError as e:
                messages.error(request, 'session key not found')
                return redirect(redirect_url)
            except ValueError as e:
                messages.error(request, e.message)
                return redirect(redirect_url)
            else:
                if session:
                    return view_func(request, *args, **kwargs)
                else:
                    return redirect(redirect_url)
        return __session_required
    return _session_required
"""


def event_session_check(request, event_key):

    session_key = 'event_%s' % event_key
    if session_key not in request.session or request.session[session_key] != True:

        next = request.get_full_path()
        next = urlquote_plus(next)
        next = iri_to_uri(next)

        login_path = reverse('event-manage-login', args=[event_key])
        redirect_url = login_path + '?next=' + next

        return redirect_url

    return None

#@event_session_required
def event_manage(request, event_key):
    check_session = event_session_check(request, event_key)
    if check_session:
        return redirect(check_session)

    try:
        eventset = EventSet.objects.get(key=event_key)
    except EventSet.DoesNotExist:
        raise Http404

    template = 'event/manage.html'
    return render(request, template, {'eventset' : eventset })


#@event_session_required
def event_manage_detail(request, event_key, detail_key:
    check_session = event_session_check(request, event_key)
    if check_session:
        return redirect(check_session)

    try:
        eventset = EventSet.objects.get(key=event_key)
    except EventSet.DoesNotExist:
        raise Http404

    event_details = eventset.details.all()

    template = 'event/manage_detail.html'
    return render(request, template, {
        'eventset' : eventset,
        'event_details': event_details
    })

固定!!!

是的!谢谢@V Stoykov和@Aldian Fazrihady,最后我修复了我的代码。现在效果很好。

urls.py:

from django.conf.urls import patterns, url

urlpatterns = patterns('event.views.manage',
    url(r'^(?P<event_key>\w+)/login$', 'event_login', name='event-manage-login'),
    url(r'^(?P<event_key>\w+)/logout$', 'event_logout', name='event-manage-logout'),
    url(r'^(?P<event_key>\w+)/manage$', 'event_manage', name='eventset.manageid '),
    url(r'^(?P<event_key>\w+)/edit$', 'event_manage_detail', name='event-manage-detail')
)

decorator.py:

def event_session_required(view_func):
    def _session_required(request, *args, **kwargs):
        next = request.get_full_path()
        event_key = kwargs.get('event_key', '')

        login_path = reverse('event-manage-login', args=[event_key])
        redirect_url = login_path + '?next=' + next

        session_key = 'event_%s' % event_key
        try:
            session = request.session.get(session_key)

        except KeyError:
            return redirect(redirect_url)

        except ValueError:
            return redirect(redirect_url)

        else:
            if session is None:
                del request.session[session_key]
                return redirect(redirect_url)

            return view_func(request, *args, **kwargs)

    return _session_required

manage.py

def event_login(request, event_key):
    ...

    try:
        eventset = EventSet.objects.get(key=event_key)
    except EventSet.DoesNotExist:
        raise Http404
    next request.GET.get('next', '')

    if request.method == 'POST':
        if eventset.manageid == request.POST.get('manageid', '') and eventset.managepwd == request.POST.get('managepwd', '') and eventset.manageid and eventset.managepwd:
        ......
            return redirect(next)
        else:
            ......

    ...

@event_session_required
def event_manage(request, event_key):

    try:
        eventset = EventSet.objects.get(key=event_key)
    except EventSet.DoesNotExist:
        raise Http404

    template = 'event/manage.html'
    return render(request, template, {'eventset' : eventset })


@event_session_required
def event_manage_detail(request, event_key, detail_key:

    try:
        eventset = EventSet.objects.get(key=event_key)
    except EventSet.DoesNotExist:
        raise Http404

    event_details = eventset.details.all()

    template = 'event/manage_detail.html'

    return render(request, template, {
        'eventset' : eventset,
        'event_details': event_details
    })


def event_logout(request, event_key):

    session_key = 'event_%s' % event_key
    try:
        del request.session[session_key]
    except:
        pass

    return redirect(reverse('event-manage', args=[event_key]))

2 个答案:

答案 0 :(得分:0)

我看到一个问题和一个可能的问题。

问题是你的装饰者event_session_required不接受任何参数。相反,真正的装饰者是其中的函数_session_required

使用当前代码(如果未注释),如果要装饰函数,则需要调用装饰器。例如:

@event_session_required()
def event_manage(request, event_key):
    ....

如果您不需要将任何参数传递给event_session_required,您可以直接接收view_func并删除_session_required功能。

def event_session_required(view_func):
    @wraps(view_func)
    def __session_required(request, *args, **kwargs):
        ...

@event_session_required
def event_manage(request, event_key):
    ...

在您的包装视图__session_required中也存在一个可能的问题。我不知道你如何描述urls.py中的网址,但从我看到的情况来看,我认为它是位置参数而不是关键字。在__session_required您期望的关键字。

您有两种选择:

  1. 将网址定义更改为使用关键字参数
  2. 要确保将使用event_session_required修饰的每个函数都接收event_key作为第一个位置参数(request之后),并将__session_required更改为第一个参数而不是关键字。
  3. 我会建议No.1

答案 1 :(得分:0)

我从不像event_session_required那样创建最外层的函数。 我总是直接去函数_session_required(view),所以装饰器将是@_session_required。

而不是在kwargs中搜索event_key,而是尝试在args中找到它。