# coding: utf-8
"""
some decorators
~~~~~~~~~~~~~~~
from PyLucid decorators.
Last commit info:
~~~~~~~~~~~~~~~~~
$LastChangedDate:$
$Rev:$
$Author: JensDiemer $
:copyleft: 2009-2010 by the PyLucid team, see AUTHORS for more details.
:license: GNU GPL v3 or above, see LICENSE for more details.
"""
import sys
import warnings
try:
from functools import wraps
except ImportError:
from django.utils.functional import wraps# Python 2.3, 2.4 fallback.
from django.conf import settings
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.contrib.auth.models import Permission
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse,HttpResponseRedirect
def check_permissions(superuser_only, permissions=()):
"""
Protect a view and limit it to users witch are log in and has the permissions.
If the user is not log in -> Redirect him to a log in view with a next_url back to the requested page.
TODO: Add a log entry, if user has not all permissions.
Usage:
--------------------------------------------------------------------------
@check_permissions(superuser_only=False, permissions=(u'appname.add_modelname', u'appname.change_modelname'))
def my_view(request):
...
--------------------------------------------------------------------------
"""
assert isinstance(superuser_only, bool)
assert isinstance(permissions, (list, tuple))
def _inner(view_function):
@wraps(view_function)
def _check_permissions(request, *args, **kwargs):
user = request.user
if not user.is_authenticated():
#FIXME: HttpResponseRedirect to admin login?
msg = _("Permission denied for anonymous user. Please log in.")
if settings.DEBUG: # Usefull??
warnings.warn(msg)
raise PermissionDenied(msg)
if not user.has_perms(permissions):
msg = "User %r has not all permissions: %r (existing permissions: %r)" % (
user, permissions, user.get_all_permissions()
)
if settings.DEBUG: # Usefull??
warnings.warn(msg)
raise PermissionDenied(msg)
return view_function(request, *args, **kwargs)
# Add superuser_only and permissions attributes, so they are accessible
# Used to build the admin menu
_check_permissions.superuser_only = superuser_only
_check_permissions.permissions = permissions
return _check_permissions
return _inner
def render_to(template_name=None, debug=False):
"""
Based on the decorators from django-annoying.
Example:
@render_to('foo/template.html')
def PyLucidPluginFoo(request):
bar = Bar.object.all()
return {'bar': bar}
The view can also insert the template name in the context, e.g.:
@render_to
def PyLucidPluginFoo(request):
bar = Bar.object.all()
return {'bar': bar, 'template_name': 'foo/template.html'}
TODO: merge render_to() and render_pylucid_response()
"""
def renderer(function):
@wraps(function)
def wrapper(request, *args, **kwargs):
context = function(request, *args, **kwargs)
if not isinstance(context, dict):
if debug:
print function.__name__, template_name, type(context), function.func_code
return context
template_name2 = context.pop('template_name', template_name)
assert template_name2 != None, \
("Template name must be passed as render_to parameter"
" or 'template_name' must be inserted into context!")
response = render_to_response(template_name2, context, context_instance=RequestContext(request))
if debug:
print "render debug for %r (template: %r):" % (function.__name__, template_name2)
print "local view context:", context
print "response:", response.content
return response
return wrapper
return renderer
|