2012-06-19 49 views
5

Estoy trabajando en un producto que permite a diferentes escuelas administrar su contenido en línea.Django Grupos y Permisos. ¿Extendiendo grupos para tener un FK?

Parte de esto implica la configuración de una lógica de control de acceso basada en roles que he escrito yo mismo. Esencialmente, cada escuela tiene su propio conjunto de roles que tienen su propio conjunto de permisos. Un usuario del software podría pertenecer a varias escuelas con roles diferentes en un momento dado.

Por varias razones, quiero deshacerme de esto y en su lugar usar los grupos y permisos de Django junto con una biblioteca como django-guardian. El problema al que me estoy enfrentando es cómo ampliar el modelo de Grupos para poder incluir una clave externa en cada escuela nueva y poder utilizar los métodos de ayuda en Django y también bibliotecas como django-guardián.

Un posible enfoque que se me ocurrió es simplemente crear grupos basados ​​en nombres de eventos como 'Escuela 1 - Administrador', 'Escuela 1 - Profesor', 'Escuela 2 - Administrador', 'Escuela 2 - Profesor' y permisos de consulta basados ​​en esto en su lugar. ¿Hay alguna buena razón por la que no debería hacerlo de esta manera?

+0

posible duplicado de [django relación uno a muchos] (http://stackoverflow.com/questions/10975140/django-one-to- many-relation) – jpic

Respuesta

0

¿Por qué no mezclar ambos enfoques en? El modelo Django permite inheritence. Primero defina el modelo Role, con roles permitidos y un modelo de escuela.

A continuación, puede heredar un nuevo modelo de django.contrib.auth.Group decir GroupRole. Django creará una nueva tabla db para su modelo que solo contiene las propiedades que no están originalmente en el grupo con una clave externa para el grupo apropiado con restricciones. Aún mejor, obtendrá una relación inversa automática al modelo grupo original, por lo que puede escribir algo como:

class GroupRole(Group): 
    role = models.ForeignKey(Role) 
    school = models.ForeignKey(School) 
    ... 

g = Group.objects.get(id=1) 
# you can access standard group items here g.<attribute> or g.grouprole.<attribute> 
# you can access GroupRole attributes by doing g.grouprole.<some_attribute> 

GroupRole.objects.filter(role__type='admin', school__location__state='NY') 

En una nota de diversión, la relación es reflexiva así que algo como esto es válido si no es demasiado útil:

g.grouprole.grouprole.grouprole.grouprole.role 

Si se obtiene una instancia de grupo de base que no tiene un proxy grouprole asociada a ella por lo que recibirá una excepción lanzada:

g = Group.objects.create(name='myplaingroup') 
try: 
    print g.grouprole 
except GroupRole.DoesNotExist: 
    print 'This is a normal group' 

Alternativamente puede anular este comportamiento para devolver None en lugar de generar una excepción o incluso proporcionar un GroupRole predeterminado en su lugar.