usuario677990
Estoy tratando de crear un decorador personalizado en Django pero no pude encontrar ninguna forma de hacerlo.
# "views.py"
@custom_decorator
def my_view(request):
# .......
Entonces, ¿cómo puedo crearlo en Django? y ¿dónde debería ponerlo para poder usarlo en cualquier parte de mi proyecto Django?
PhoebeB
Jugué con los diversos enlaces anteriores y no pude hacerlos funcionar y luego encontré este realmente simple que adapté. http://code.activestate.com/recipes/498217-custom-django-login_required-decorator/
from functools import wraps
from django.http import HttpResponseRedirect
def authors_only(function):
@wraps(function)
def wrap(request, *args, **kwargs):
profile = request.user.get_profile()
if profile.usertype == 'Author':
return function(request, *args, **kwargs)
else:
return HttpResponseRedirect("https://stackoverflow.com/")
return wrap
Usando @wraps
es mejor que anular manualmente como hacer wrap.__doc__ = fn.__doc__
. Entre otras cosas, garantiza que su función contenedora obtenga el mismo nombre que la función envuelta.
-
Esta debería ser la respuesta aceptada, ¡pulgares arriba! Traté de aprovechar el decorador user_passes_test pero me perdí, esto salvó el día.
– Radtek
16 de septiembre de 2014 a las 0:59
-
@radtek tengo
wrap() takes at least 1 argument (0 given)
. ¿Alguna pista para solucionarlo?– Ardiano
16 de agosto de 2015 a las 16:14
-
Tendría que ver su código, pero lo más probable es que no haya pasado la solicitud a la función que está decorando.
– Radtek
18 de agosto de 2015 a las 17:53
-
la
@wraps
El método es solo para documentos, por lo que podría omitirlo, ¿verdad?– Sven
3 de mayo de 2020 a las 14:07
ario
No tienes que escribir tu propio decorador para esto como user_passes_test
ya está incluido en Django.
Y hay un fragmento (group_required_decorator
) que amplía este decorador y que debería ser bastante apropiado para su caso de uso.
Si realmente quieres escribir tu propio decorador, entonces hay un montón de buena documentacion en la red.
Y bueno, para (re)utilizar el decorador simplemente coloque su decorador en un módulo en su ruta y puede importarlo desde cualquier otro módulo.
-
def souk_required(): “””Requiere que el usuario sea miembro de al menos uno de los grupos pasados.””” def has_souk(u): if u.is_authenticated(): if bool(SoukUsers.objects.get(person = u) ): return True return False(u) return user_passes_test(has_souk)
– usuario677990
29 de marzo de 2011 a las 8:18
-
da este error – souk_required no toma argumentos (1 dado)
– usuario677990
29 de marzo de 2011 a las 8:19
-
Hm .. Accidentalmente voté a favor de su comentario 😉 Bueno, eliminó el argumento esperado de la definición de su función y, por lo tanto, recibió el error dado. Entonces, ¿qué hay de crear un grupo de “usuarios premium” y agregar sus usuarios a ese grupo? Luego puede usar el fragmento tal como está y simplemente pasar el nombre de su grupo.
– arie
29 de marzo de 2011 a las 8:31
-
No es tu culpa que nos pase a los mejores; ]…. de todos modos muchas gracias hombre… Te debo mucho tiempo.
– usuario677990
29 de marzo de 2011 a las 8:42
Gracias a arie, la respuesta ayudó mucho, pero no me funciona.
Cuando encontré este fragmento, conseguí que funcionara correctamente: http://djangosnippets.org/snippets/983/
Esta solución funcionó para mí:
La función auxiliar
Esta función tiene la ventaja de ser reutilizable en otros lugares, como reemplazo directo de user.is_authenticated
. Podría, por ejemplo, exponerse como una etiqueta de plantilla.
def my_custom_authenticated(user):
if user:
if user.is_authenticated():
return user.groups.filter(name=settings.MY_CUSTOM_GROUP_NAME).exists()
return False
el decorador
Acabo de poner esto en la parte superior de mi views.py
ya que es muy corto.
def membership_required(fn=None):
decorator = user_passes_test(my_custom_authenticated)
if fn:
return decorator(fn)
return decorator
usándolo
@membership_required
def some_view(request):
...
Ver ejemplos en Django mismo:
http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/decorators.py
Su ejemplo particular es probablemente solo una versión de ‘user_passes_test’ donde la prueba será membresía del grupo ‘premium’.
Para usar en cualquier lugar, cree un paquete de python e impórtelo desde allí. Siempre que esté en su sys.path, se encontrará.
Aquí hay una implementación ligeramente diferente, que permite parámetros adicionales para especificar a qué página redirigir cuando falla la validación y qué mensaje mostrar al usuario final:
from functools import wraps
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from core.helpers.flash import send_flash_error
def lender_only(redirect_to='plateforme.views.vue_login', error_flash_message=None):
def inner_render(fn):
@wraps(fn) # Ensure the wrapped function keeps the same name as the view
def wrapped(request, *args, **kwargs):
if request.context.user.is_authenticated and request.context.user.is_lender:
return fn(request, *args, **kwargs)
else:
if error_flash_message:
send_flash_error(request, error_flash_message) # Replace by your own implementation
return HttpResponseRedirect(reverse(redirect_to))
return wrapped
return inner_render
# Usage:
@lender_only('vitrine.views.projets', {'message': "Oops, can't go there."})
def render_page_index(request):
Esta guía me ayudó a superarlo: https://elfsternberg.com/2009/11/20/python-decorators-with-arguments-with-bonus-django-goodness/ junto con las respuestas anteriores
http://www.makina-corpus.org/blog/permission-required-decorator-django
basé el mío en esa publicación de blog.
Pegue eso en un archivo en la ruta de Python o en una aplicación “util” e impórtelo a las vistas:
p.ej
project_dir
|_ app1
|_ app2
|_ utils
|_ __init__.py
|_ permreq.py
from util.permreq import permission_required
@permmission_required('someapp.has_some_perm', template="denied.html")
def some_view(request):
blah blah
from django.contrib.auth.decorators import user_passes_test
from django.core.exceptions import PermissionDenied
def perm_group_required(group, login_url="https://stackoverflow.com/", raise_exception=False):
def check_group(user):
if user.groups.filter(name=group).exists():
return True
# In case the 403 handler should be called raise the exception
if raise_exception:
raise PermissionDenied
return False
return user_passes_test(check_group, login_url=login_url)
@perm_group_required('add_customer_group')
#group name="add_customer_group"
def employee_add_customer(request):
##logic
...
-
Que es
#group name="add_customer_group"
? Cualquier enlace sobre cómo hacer un decorador con un objeto que tiene unBooleanField
?– Usuario anónimo
6 ago a las 4:36
-
name=”add_customer_group” es un nombre de grupo de permisos y ese nombre de grupo de permisos se asigna a un usuario autenticado; si algún usuario autenticado tiene este permiso, puede acceder a la función de vista
– Prashan Basantia
6 ago a las 6:16