2012-08-09 8 views
14

¿Hay una manera de hacer los permisos de nivel de fila en Django? Pensé que no era pero sólo se dio cuenta de esto en los documentos:nivel de fila en Django

permisos se pueden configurar no sólo por el tipo de objeto, sino también por instancia de objeto específico. Mediante el uso de los métodos has_add_permission(), has_change_permission() y has_delete_permission() proporcionados por la clase ModelAdmin, es posible personalizar los permisos para instancias de objetos diferentes del mismo tipo.

https://docs.djangoproject.com/en/dev/topics/auth/

Pero no veo ninguna documentación sobre cómo aplicar en la práctica por los permisos de instancia

Respuesta

0

Hay un gran número de aplicaciones "permisos" para Django available on PyPi
Por ejemplo, podría mira django-object-permission.

Lo que la documentación se refiere es que la funcionalidad está ahí para poner en práctica los permisos. Y la gente lo ha hecho creando aplicaciones para esto.

5

La cañería es allí (esto es desde la parte inferior de la misma página se enlazó):

Manejo de permisos de objetos

marco permiso de Django tiene una base de permisos de objetos, aunque no hay implementación para ello en el núcleo. Eso significa que la comprobación de permisos de objetos siempre devolverá falso o una lista vacía (dependiendo de la comprobación realizada ). Un motor de autenticación recibirá la palabra clave parámetros obj y user_obj para cada método de autorización relacionada objeto y puede devolver el permiso de nivel de objetos según el caso.

Pero no se proporciona ninguna aplicación por defecto. Dado que este es un tema común; hay muchos answers en SO. Verifica a la derecha y verás algunos en la lista.

idea

La base es para navegar por la django packages' perm grid y recoger una implementación de permisos de nivel de objeto. Personalmente me gusta django-guardian.

6

Los métodos que los documentos hablan de le permitirá restringir el acceso a determinados objetos en el admin. Cada método se pasa el objeto en el juego, que se puede utilizar para hacer determinaciones acerca de si un usuario puede acceder a ella, ya sea mediante la devolución de 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 
+0

Cabe señalar que [hay un error en Django (# 11383)] (https://code.djangoproject.com/ticket/11383) que impide la comprobación de permisos de nivel de objeto cuando el "Borrar selección" acción de administración se ejecuta. – jnns

+0

¿Usted sabe cómo hacer lo mismo con 'admin.TabularInline'? – xleon

24

Para una aplicación estoy construyendo quiero dar permiso a nivel de fila a través de un simple decorador. Puedo hacer esto porque la condición es simplemente si request.user es el propietario del objeto modelo.

Siguiendo 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 comentarios son apreciados.

Paul Borman

Cuestiones relacionadas