Django authentication and Ajax - URLs that require login

前端 未结 5 1144
暗喜
暗喜 2020-11-29 15:45

I want to add some Ajax-niceness to my Django-coded website.

In my Django code, I use the @login_required decorator from django.contrib.auth.deco

相关标签:
5条回答
  • 2020-11-29 16:24

    I would agree with S.Lott

    Make a check in the template, if the user is logged in, just put the link as usual, if not, put something like

    <a href="{{link}}" onclick="return login_popup()"> 
    

    where login_popup would return false if the user says cancel.

    This could be probably be done much easier in Jinja2 through its macros.

    If the template doesn't know which urls require the user to login, you probably need to re-consider your design.

    If you must, I guess you can do the same thing that the django url dispatcher does to discover the view function.
    see: django.core.urlresolvers

    once you've grabbed the view function you can check if it's decorated with @login_required.

    This would be done in a custom tag probably.
    If you use Jinja2, you won't need the tag, just implement the function and expose it to the Environment, it's simple but you'll have to do a bit of reading on the API of Jinja2)

    0 讨论(0)
  • 2020-11-29 16:34

    Here is proposed version of the decorator with wrap.__doc__ , wrap.__name__

    from functools import wraps
    
    def ajax_login_required(function):
        def wrap(request, *args, **kwargs):
            if request.user.is_authenticated():
                return function(request, *args, **kwargs)
            json = simplejson.dumps({ 'not_authenticated': True })
            return HttpResponse(json, mimetype='application/json')  
        wrap.__doc__ = function.__doc__
        wrap.__name__ = function.__name__
        return wrap
    
    0 讨论(0)
  • 2020-11-29 16:36

    I am facing the same issue, and, like you, I would like a simple decorator to wrap around a Django ajax view in order to handle authentication in the same way that I have other views. One approach that seems promising to me is to use such a decorator in conjunction with JavaScript that looks for a certain value in the response.

    Here is first revised draft of the decorator:

    from functools import wraps
    
    def ajax_login_required(view_func):
        @wraps(view_func)
        def wrapper(request, *args, **kwargs):
            if request.user.is_authenticated():
                return view_func(request, *args, **kwargs)
            json = simplejson.dumps({ 'not_authenticated': True })
            return HttpResponse(json, mimetype='application/json')
        return wrapper
    

    Here is the view:

    @ajax_login_required
    def ajax_update_module(request, module_slug, action):
        # Etc ...
        return HttpResponse(json, mimetype='application/json')
    

    And here is the JavaScript (jQuery):

    $.post('/restricted-url/', data, function(json) {
        if (json.not_authenticated) {
            alert('Not authorized.');  // Or something in a message DIV
            return;
        }
        // Etc ...
    });
    

    EDIT: I've attempted to use functools.wraps, as suggested. I have not actually used this decorator in working code, so beware of possible bugs.

    0 讨论(0)
  • 2020-11-29 16:38

    Built off of Eric Walker's solution, but for Django 2.0

    # Standard Imports
    import functools
    import django.http
    
    def ajax_login_required(view_func):
        @functools.wraps(view_func)
        def wrapper(request, *args, **kwargs):
            if request.user.is_authenticated:
                return view_func(request, *args, **kwargs)
    
            return django.http.JsonResponse('Unauthorized', status=401, safe=False)
    
        return wrapper
    
    0 讨论(0)
  • 2020-11-29 16:41

    Sounds like a page template possibility.

    1. You could pass a LINK_VIA (or something) that you provide as onClick="return popup(this, 'arg')" or None. Each link would be <A HREF="link" {{LINK_VIA}}>some text</a>.

      • For anonymous sessions, LINK_VIA has a value.
      • For logged in sessions, LINK_VIA is None
    2. You could use an {% if %} statement around your <A HREF=...> tags. This seems wordy.

    3. You could write your own custom tag with for {% link_via %}. I'm not familiar enough with this, but you can provide the link and text as strings and your tag can generate one of two kinds of links.

    0 讨论(0)
提交回复
热议问题