Source code for permission.decorators.functionbase

# coding=utf-8
"""
permission_required decorator for generic function view
"""
__author__ = 'Alisue <lambdalisue@hashnote.net>'
import copy
from functools import wraps
from django.shortcuts import get_object_or_404
from django.utils.decorators import available_attrs
from django.core.exceptions import PermissionDenied

from permission.decorators.utils import redirect_to_login


[docs]def permission_required(perm, queryset=None, login_url=None, raise_exception=False): """ Permission check decorator for function-base generic view This decorator works as function decorator Parameters ---------- perm : string A permission string queryset_or_model : queryset or model A queryset or model for finding object. With classbased generic view, ``None`` for using view default queryset. When the view does not define ``get_queryset``, ``queryset``, ``get_object``, or ``object`` then ``obj=None`` is used to check permission. With functional generic view, ``None`` for using passed queryset. When non queryset was passed then ``obj=None`` is used to check permission. Examples -------- >>> @permission_required('auth.change_user') >>> def update_auth_user(request, *args, **kwargs): ... pass """ def wrapper(view_func): @wraps(view_func, assigned=available_attrs(view_func)) def inner(request, *args, **kwargs): _kwargs = copy.copy(kwargs) # overwrite queryset if specified if queryset: _kwargs['queryset'] = queryset # get object from view if 'date_field' in _kwargs: fn = get_object_from_date_based_view else: fn = get_object_from_list_detail_view if fn.validate(request, *args, **_kwargs): obj = fn(request, *args, **_kwargs) else: # required arguments is not passed obj = None if not request.user.has_perm(perm, obj=obj): if raise_exception: raise PermissionDenied else: return redirect_to_login(request, login_url) return view_func(request, *args, **_kwargs) return inner return wrapper
[docs]def get_object_from_list_detail_view(request, *args, **kwargs): """ Get object from generic list_detail.detail view Parameters ---------- request : instance An instance of HttpRequest Returns ------- instance An instance of model object or None """ queryset = kwargs['queryset'] object_id = kwargs.get('object_id', None) slug = kwargs.get('slug', None) slug_field = kwargs.get('slug_field', 'slug') if object_id: obj = get_object_or_404(queryset, pk=object_id) elif slug and slug_field: obj = get_object_or_404(queryset, **{slug_field: slug}) else: raise AttributeError( "Generic detail view must be called with either an " "object_id or a slug/slug_field." ) return obj
def _get_object_from_list_detail_view_validation(request, *args, **kwargs): if 'queryset' not in kwargs: return False elif 'object_id' not in kwargs and 'slug' not in kwargs: return False return True get_object_from_list_detail_view.validate = \ _get_object_from_list_detail_view_validation
[docs]def get_object_from_date_based_view(request, *args, **kwargs): """ Get object from generic date_based.detail view Parameters ---------- request : instance An instance of HttpRequest Returns ------- instance An instance of model object or None """ import time import datetime from django.http import Http404 from django.db.models.fields import DateTimeField try: from django.utils import timezone datetime_now = timezone.now except ImportError: datetime_now = datetime.datetime.now year, month, day = kwargs['year'], kwargs['month'], kwargs['day'] month_format = kwargs.get('month_format', '%b') day_format = kwargs.get('day_format', '%d') date_field = kwargs['date_field'] queryset = kwargs['queryset'] object_id = kwargs.get('object_id', None) slug = kwargs.get('slug', None) slug_field = kwargs.get('slug_field', 'slug') try: tt = time.strptime( '%s-%s-%s' % (year, month, day), '%s-%s-%s' % ('%Y', month_format, day_format) ) date = datetime.date(*tt[:3]) except ValueError: raise Http404 model = queryset.model if isinstance(model._meta.get_field(date_field), DateTimeField): lookup_kwargs = { '%s__range' % date_field: ( datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max), )} else: lookup_kwargs = {date_field: date} now = datetime_now() if date >= now.date() and not kwargs.get('allow_future', False): lookup_kwargs['%s__lte' % date_field] = now if object_id: lookup_kwargs['pk'] = object_id elif slug and slug_field: lookup_kwargs['%s__exact' % slug_field] = slug else: raise AttributeError( "Generic detail view must be called with either an " "object_id or a slug/slug_field." ) return get_object_or_404(queryset, **lookup_kwargs)
def _get_object_from_date_based_view_validation(request, *args, **kwargs): if 'queryset' not in kwargs: return False elif 'year' not in kwargs or 'month' not in kwargs or 'day' not in kwargs: return False elif 'object_id' not in kwargs and 'slug' not in kwargs: return False return True get_object_from_date_based_view.validate = \ _get_object_from_date_based_view_validation