Una gran comunidad de saludos

Mi pregunta está relacionada con el tipo de administración de usuarios y el esquema de usuarios en Django. Al principio le pido disculpas por si mis preguntas pueden ser demasiado "novatas" o sin sentido, estoy empezando a relacionarme con Django. Esquemas de usuarios y sus diferentes posibilidades de trabajo en los proyectos.

Tengo la siguiente situación.

Estoy creando una aplicación en la que tendré tres tipos de usuarios diferentes:

  • Médica
  • Paciente
  • Fisioterapeuta

Estoy usando el esquema de autenticación predeterminado de Django (django.contrib.auth).

Inicialmente, pensé en este esquema de entidades en las que la tabla Usuario es la tabla auth_user en la que Django guarda los usuarios creados:

Schema thinked (bad  - ?)

Tengo los campos is_patient, is_medical y is_physiotherapist como atributos booleanos en la tabla Usuario.

Como un detalle particular, entiendo que en el modelo predeterminado de Django, el usuario no es posible modificar o agregar atributos o campos.

Esta es una razón importante y poderosa para no poder agregar los campos booleanos is_patient, is_medical y is_physiotherapist en la tabla Usuario.

Una recomendación clásica es extender el modelo de usuario con una tabla de perfil de usuario en la que agrego campos o atributos al modelo de usuario a través de la relación OneToOne. Una muestra básica es la siguiente:

Extending Django users model

Es de esta manera que entiendo que mis usuarios en Django pueden tener la foto de campo y subir una en un momento dado ...

Aprovechando lo anterior, El siguiente esquema puede ser adecuado o puede ser una alternativa para administrar roles de usuario (patient, medical y physiotherapist tipos de usuario)?

Other schema thinked

Tendré relaciones entre:

  • Usuario médico y pacientes usuarios

  • usuario fisioterapeuta y pacientes usuarios

Y así entre ellas y otras mesas ...

Con este enfoque, estas relaciones no se verán afectadas?

Los diferentes usuarios se guardarán entre la tabla Users y UserProfile. ¿Es esta una buena práctica en el sentido de escalabilidad? ¿Mis tablas podrían estar bloqueadas o mi base de datos?


Además, también he visto otras alternativas como:

  1. Tabla de roles / modelo

Tendré una tabla / modelo de roles independiente o separada y esto puede estar relacionado con el modelo de usuario de Django (un usuario puede tener muchos roles por ejemplo) Este enfoque puede ser útil cuando quiero almacenar información exclusiva sobre un rol en especial ?

  1. Permisos y autorización de Django

Ignoro o desconozco el grado de granularidad que me permitió trabajar. De una sola manera, he visto que el sistema de permisos y autorizaciones me permitirá trabajar con las operaciones de creación, edición y eliminación ...

Aquí, ¿puedo ver la creación de grupos? Por ejemplo, un grupo médico y asignarles permisos y vincular estos permisos a los usuarios que componen el grupo? ¿Es esta otra buena alternativa? Esta opción parece más simple, aunque no sé si un usuario podría realizar algunas operaciones de acuerdo con los privilegios del grupo que tiene ... No sé si este pensamiento es correcto / correcto

  1. AUTH_USER_MODEL Creación de un modelo de usuario personalizado

¿Mis requisitos para usuarios de pacientes, médicos y fisioterapeutas requieren construir un modelo de usuario personalizado?

7
bgarcial 11 dic. 2015 a las 01:42

4 respuestas

La mejor respuesta

En esta situación, especialmente si desea almacenar información diferente para pacientes, médicos y fisioterapeutas, puede crear un modelo para cada uno y tener un campo OneToOne para cada modelo de usuario.

class Medic(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    # other fields

class Physio(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    # other fields

class Patient(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    # other fields

De esta manera, puede otorgar diferentes permisos / roles implícitamente en la lógica de su aplicación para cada tipo de usuario (y aún usar los grupos y permisos que ofrece Django si los necesita para casos especiales, por ejemplo, ChiefMedical ...).

Tendrá que definir algunos métodos para la lógica de su aplicación, como

def user_is_patient(user):
     ...

Si sigue este camino, es una buena idea hacerse buenas pruebas para asegurarse de que no reciba cosas inesperadas como un usuario que es un médico y un fisio ...

Django también te permite subclasificar el modelo de usuario. Debajo de las cubiertas, haría lo mismo que el código anterior, por lo que probablemente sea mejor hacerlo explícitamente como se muestra arriba (¡de esta manera es menos probable que acceda a atributos que no existen en ese objeto!)

¿Aprovechando lo anterior, el siguiente esquema puede ser adecuado o puede ser una alternativa para gestionar los roles de los usuarios (pacientes, médicos y fisioterapeutas)?

El esquema que muestra no es excelente porque le permite almacenar la información para todos los tipos de usuarios en la misma tabla (y con los mismos campos). Por ejemplo, Médicos y Fisios tendrán un tipo de campo de tipo de sangre como Pacientes que probablemente no se definirá.

Los diferentes usuarios se guardarán entre la tabla Users y UserProfile. ¿Es esta una buena práctica en el sentido de escalabilidad? ¿Mis tablas podrían estar bloqueadas o mi base de datos?

No debería haber problemas de escalabilidad con esta solución (siempre que no tenga millones de nuevas entradas escritas todos los días) y siempre puede optimizar la base de datos en otro momento. Sin embargo, tendrá que asegurarse de que su aplicación no acepte entradas 'prohibidas' (por ejemplo, usuarios sin perfil de Medic, Physio o Patient)

Aquí, ¿puedo ver la creación de grupos? Por ejemplo, un grupo médico y asignarles permisos y vincular estos permisos a los usuarios que componen el grupo? ¿Es esta otra buena alternativa? Esta opción parece más simple, aunque no sé si un usuario podría realizar algunas operaciones de acuerdo con los privilegios del grupo que tiene ... No sé si este pensamiento es correcto / correcto

Puede (debe) usar el sistema de permisos de Django para otorgar permisos a sus usuarios. Puede usarlos para otorgar diferentes derechos a los usuarios del mismo tipo (por ejemplo, médicos que tienen más permisos que otros ... o tienen grupos para los físicos principales ...)

Django le permite asignar permisos a un grupo.

Pero no creo que los grupos puedan reemplazar los modelos personalizados para cada usuario, ya que desea almacenar información para ellos. Tener modelos y grupos personalizados sería redundante y haría que su aplicación sea más difícil de mantener.

¿Mis requisitos para usuarios de pacientes, médicos y fisioterapeutas requieren construir un modelo de usuario personalizado?

Esta opción no sería excelente (a menos que sea su única opción) porque su aplicación no será reutilizable y es posible que también tenga problemas con algunos paquetes.

7
Ire 14 dic. 2015 a las 09:31

Puede crear un modelo de usuario personalizado o no, en cualquier caso, podría tener tres modelos separados para almacenar datos pertinentes, dependiendo de si el usuario es paciente, médico, fisioterapeuta o cualquier combinación de estos.

Si su esquema de permisos está determinado únicamente por el rol (paciente, médico, fisioterapeuta), entonces no necesita usar el sistema de permisos de Django, porque conoce los roles de cualquier usuario y puede, en el peor de los casos, codificar Reglas de autorización.

3
Lorenzo Peña 13 dic. 2015 a las 10:07

@geoom @Ire @ lorenzo-peña He creado un usuario a través del sitio de administración de Django y verifiqué sus atributos (is_medical, is_patient, is_physiotherapist) a través de Python Shell

In [6]: User.objects.filter(username='agarcial').values('is_medical','is_patient','is_physiotherapist')

Out[6]: [{'is_physiotherapist': True, 'is_patient': True, 'is_medical': True}]

Por el momento en mi views.py, estoy haciendo que un usuario inicie sesión solo cuando este sea uno de los tres tipos de usuario (médico, paciente o fisioterapeuta)

# Create your views here.


class ProfileView(LoginRequiredMixin, TemplateView):
    template_name = 'profile.html'
    def get_context_data(self, **kwargs):
        self.request.session['Hi'] = True
        context = super(ProfileView, self).get_context_data(**kwargs)
        is_auth = False
        name = None
        # Check if in the request goes the user
        user = self.request.user

        # Check about of possible cases (For now is one profile)
        if user.is_medical:
        #if self.request.user.is_authenticated():
            print (user.is_medical)
            is_auth = True
            profile=user.get_medical_profile()
            #name = self.request.user.username

            data = {
                'is_auth':is_auth,
                'profile':profile,
            }

            context.update({'userprofile':profile, 'data':data})
        elif user.is_patient:
            print (user.is_patient)
            is_auth=True
            profile=user.get_patient_profile()

            data = {
                'is_auth':is_auth,
                'profile':profile,
            }
            context.update({'userprofile':profile,'data':data})
        elif user.is_physiotherapist:
            print (user.is_physiotherapist)
            is_auth=True
            profile=user.get_physiotherapist_profile()

            data = {
                'is_auth':is_auth,
                'profile':profile,
            }
            context.update({'userprofile':profile,'data':data})
        return  context

    def get_userprofile(self):
        return self.request.user.userprofile

Si verifico las otras combinaciones posibles (paciente paciente, médico y fisioterapeuta), ¿esto podría funcionar?

Creo que creo grupos para (médicos, pacientes, fisioterapeutas) y usuarios vinculantes para el tema de autorización, aunque debería revisar otras cosas para el proceso de autorización, como django guardian por ejemplo?

¿Qué te parece esto?

0
Uncle Iroh 30 ene. 2018 a las 16:41

Eché un vistazo a los comentarios de las preguntas y veo algunos problemas:

(https://cldup.com/jxVsgfneGb.png)

Me di cuenta de que su modelo de usuario no coincide con el modelo de datos original ya que tiene get_medical_profile, get_patient_profile y get_physiotherapist_profile funciones dentro del modelo de usuario, con lo que está asumiendo que cualquier usuario podría tener múltiples perfiles al mismo tiempo, que no se refleja ni en sus modelos de perfil (médico, paciente y fisioterapeuta) que usan OneToOneField ni en el modelo de datos original de la pregunta, es algo importante sobre la abstracción y la responsabilidad de clase. El requisito (según el modelo a continuación) parece decir "un usuario puede tener un solo perfil".

enter image description here

Entonces, creo que esto se puede resolver de una manera directa y limpia, no es necesario que participe en el esquema general de autenticación, como grupos y permisos, o agregue atributos adicionales al modelo de usuario:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    # common fields shared by medical, patient and physiotherapist profiles

class MedicalUser(models.Model):
    profile = models.OneToOneField(UserProfile)
    # medical fields here

class PatientUser(models.Model):
    profile = models.OneToOneField(UserProfile)
    # patient fields here

class PhysiotherapistUser(models.Model):
    profile = models.ForeignKey(UserProfile)
    # patient fields here

Como puede ver, puede tener un perfil que contenga campos comunes compartidos por todos los perfiles. y cada perfil tiene un modelo específico.

Además, puede verificar si el usuario es médico mediante esta pequeña función a continuación, luego, si no hay un perfil médico asociado con el perfil, generará una excepción y significa que es un perfil no especificado:

def is_medical_profile(profile):
    try:
        profile.medical_user
        return True
    except:
        return False

También puede usarlo en sus plantillas (como una etiqueta de plantilla personalizada) de esta manera:

{% if profile | is_medical_profile %}

Con este enfoque no necesita configurar AUTH_USER_MODEL

Espero que esto mejore tu solución.


Notas adicionales:

En caso de que decida tener un modelo de usuario personalizado, configure los ajustes.AUTH_USER_MODEL y úselo para claves externas para el usuario.

En un fragmento de texto de un libro impresionante, Dos bolas de Django dice:

Desde Django 1.5 en adelante, la forma preferida oficial de adjuntar ForeignKey, OneToOneField o ManyToManyField al usuario

Por lo tanto, su modelo de perfil de usuario cambiaría de la siguiente manera:

from django.conf import settings
from django.db import models

class UserProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL)

Sí, parece un poco extraño, pero eso es lo que aconseja el documento oficial de Django.

2
geoom 19 dic. 2015 a las 11:17