Tengo alrededor de una docena de búsquedas de permisos que aseguran que los usuarios tengan los permisos adecuados para hacer algo en el sistema (es decir, asegurarse de que estén en el grupo correcto, si pueden editar su perfil , si son administradores de grupo, etc.).Almacenamiento en caché de devoluciones no vistas
Un cheque podría tener este aspecto:
from django.contrib.auth.decorators import user_passes_test
test_canvote = lambda u: u.has_perm('polls.can_vote')
@user_passes_test(test_canvote)
def my_view(request):
# ...
Esto es en realidad el código del tutorial de Django (el mío es un poco más feo). A veces, un control requiere mucha base de datos y genera múltiples consultas. Con muchos usuarios accediendo a páginas marcadas con permiso, las cosas pueden volverse bastante lentas rápidamente.
Mi pregunta es, ¿puedo (con su ayuda) construir un contenedor (o reemplazo) para el decorador user_passes_test que busca en el caché una clave 'TESTCACHE' + user.pk + 'testname'
y si no existe, ejecuta la prueba y guarda su resultado.
nunca he escrito un decorador antes, pero me imagino que sería casi idéntica a la user_passes_test
uno, sólo pasar la prueba como una cadena:
@cached_user_passes_test('test_canvote')
def my_view(request):
# ...
Y como siempre, quiero saber si yo estoy loco o si Django ya hace esto por mí (entonces tengo problemas en otro lado).
Editar: Los decoradores estándar se pueden encontrar aquí: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/decorators.py
yo creo que puede ser más fácil la sustitución de user_passes_test
envolviéndolo Así que aquí está el punto de partida. Por supuesto, si usted siente que soy incorrecto en esa declaración, que me haga saber:
try:
from functools import update_wrapper, wraps
except ImportError:
from django.utils.functional import update_wrapper, wraps # Python 2.3, 2.4 fallback.
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.http import HttpResponseRedirect
from django.utils.http import urlquote
from django.utils.decorators import auto_adapt_to_methods
def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
Decorator for views that checks that the user passes the given test,
redirecting to the log-in page if necessary. The test should be a callable
that takes the user object and returns True if the user passes.
"""
if not login_url:
from django.conf import settings
login_url = settings.LOGIN_URL
def decorator(view_func):
def _wrapped_view(request, *args, **kwargs):
if test_func(request.user):
return view_func(request, *args, **kwargs)
path = urlquote(request.get_full_path())
tup = login_url, redirect_field_name, path
return HttpResponseRedirect('%s?%s=%s' % tup)
return wraps(view_func)(_wrapped_view)
return auto_adapt_to_methods(decorator)
Los argumentos para la función de prueba también deberían ser parte de la clave por razones obvias. – Oli
Por supuesto, tratando de ser demasiado inteligente con el último ... editado para hacer la obtención y la configuración dentro del decorador. ¿Esto funcionaría? – ara818