how - inherit user model django
permisos de nivel de fila en django (5)
Hay un gran número de aplicaciones de "permisos" para django disponibles en PyPi
Por ejemplo, podrías mirar django-object-permission .
A lo que se refiere la documentación es que la funcionalidad está ahí para implementar los permisos. Y la gente lo ha hecho al crear aplicaciones para esto.
¿Hay una manera de hacer permisos de nivel de fila en django? Pensé que no había, pero me di cuenta de esto en la documentación:
Los permisos se pueden establecer no solo por tipo de objeto, sino también por instancia de objeto específico. Al usar los métodos has_add_permission (), has_change_permission () y has_delete_permission () proporcionados por la clase ModelAdmin, es posible personalizar los permisos para diferentes instancias de objetos del mismo tipo.
https://docs.djangoproject.com/en/dev/topics/auth/
Pero no veo ninguna documentación sobre cómo implementar realmente los permisos por instancia
He implementado una solución para este tipo de problema utilizando las vistas basadas en clases de Django.
Revise mi artículo Vistas basadas en clases genéricas de Django con verificación de permisos a nivel de objeto .
La tubería está ahí (esto es desde la parte inferior de la misma página que has vinculado):
Manejando permisos de objetos
El marco de permisos de Django tiene una base para los permisos de objetos, aunque no hay ninguna implementación para él en el núcleo. Eso significa que la verificación de los permisos de los objetos siempre devolverá Falso o una lista vacía (según la verificación realizada). Un backend de autenticación recibirá los parámetros de palabra clave obj y user_obj para cada método de autorización relacionado con el objeto y puede devolver el permiso de nivel de objeto según corresponda.
Pero no se proporciona ninguna implementación por defecto. Dado que este es un tema común; Hay muchas answers en SO. Marque a la derecha y verá algunos listados.
La idea básica es explorar la cuadrícula de permisos de los paquetes django y elegir una implementación de permisos a nivel de objeto. Personalmente me gusta el django-guardian .
Los métodos de los que hablan los documentos te permitirán restringir el acceso a objetos particulares en el administrador. A cada método se le pasa el objeto en juego, que puede usar para determinar si un usuario puede acceder a él, devolviendo True
o False
.
class MyModelAdmin(admin.ModelAdmin):
...
def has_add_permission(self, request):
# This one doesn''t get an object to play with, because there is no
# object yet, but you can still do things like:
return request.user.is_superuser
# This will allow only superusers to add new objects of this type
def has_change_permission(self, request, obj=None):
# Here you have the object, but this is only really useful if it has
# ownership info on it, such as a `user` FK
if obj is not None:
return request.user.is_superuser or /
obj.user == request.user
# Now only the "owner" or a superuser will be able to edit this object
else:
# obj == None when you''re on the changelist page, so returning `False`
# here will make the changelist page not even viewable, as a result,
# you''d want to do something like:
return request.user.is_superuser or /
self.model._default_manager.filter(user=request.user).exists()
# Then, users must "own" *something* or be a superuser or they
# can''t see the changelist
def has_delete_permission(self, request, obj=None):
# This pretty much works the same as `has_change_permission` only
# the obj == None condition here affects the ability to use the
# "delete selected" action on the changelist
Para una aplicación que estoy creando, quiero otorgar permisos a nivel de fila a través de un simple decorador. Puedo hacer esto porque la condición es solo si el request.user es el propietario del objeto modelo.
Lo siguiente parece funcionar:
from functools import wraps
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
def is_owner_permission_required(model, pk_name=''pk''):
def decorator(view_func):
def wrap(request, *args, **kwargs):
pk = kwargs.get(pk_name, None)
if pk is None:
raise RuntimeError(''decorator requires pk argument to be set (got {} instead)''.format(kwargs))
is_owner_func = getattr(model, ''is_owner'', None)
if is_owner_func is None:
raise RuntimeError(''decorator requires model {} to provide is_owner function)''.format(model))
o=model.objects.get(pk=pk) #raises ObjectDoesNotExist
if o.is_owner(request.user):
return view_func(request, *args, **kwargs)
else:
raise PermissionDenied
return wraps(view_func)(wrap)
return decorator
La vista:
@login_required
@is_owner_permission_required(Comment)
def edit_comment(request, pk):
...
Urls:
url(r''^comment/(?P<pk>/d+)/edit/$'', ''edit_comment''),
El modelo:
class Comment(models.Model):
user = models.ForeignKey(User, ...
<...>
def is_owner(self, user):
return self.user == user
Cualquier comentario o comentario son apreciados.
Paul Bormans