我不知道这是否是一个反复出现的主题,知道何时使用 Django 身份验证方案,使用和扩展它的最佳方法是什么,或者它是否被自定义的替代,但总是有这样的想法保留身份验证的机制和功能。
由于上述原因,我想分享我对以下情况的一些可能的替代方案或设计方法的担忧,希望它们可以帮助我分析/提出或选择最佳方案:
我正在构建一个应用程序,其中有三种不同类型的用户:
- 医疗的
- 病人
- 物理治疗师
所有三个用户都必须能够登录到系统,并且在医疗用户与患者用户之间以及物理治疗师用户与患者用户之间存在关系(从应用程序的业务对象或需求的上下文),了解:
- 一名患者接受医生治疗
- 一名患者接受治疗师的治疗
- 患者可以在系统中扮演这三个角色(我认为这不会有问题)
我最初的想法是使用 Django 的默认身份验证方案(django.contrib.auth)
我最初想到了以下实体模式,其中 User 模型/表相当于 Django 在我们应用第一次迁移时在我们的数据库中自动生成的 auth_user 表,其中存储了 Django 用户:
在这个 User 表中,我添加了三个布尔字段,它们是
is_patient
:is_medical
和is_physiotherapist
上一个,我认为这是一种可以让我做我正在寻找的事情的方法,只是有一个细节,那就是 Django 的默认身份验证模型不能修改,它是不可变的,我认为要修改如果你必须修改 Django 的核心,这是更昂贵的东西,或者有必要把它做好或知道正在做什么。
is_patient
因此,无法按我的意愿将is_medical
和字段添加到 User 表中。is_physiotherapist
Django 在其文档中给我们的一个经典建议是将具有 OneToOne 关系的 User 模型扩展到另一个包含我们要添加到用户的附加数据的模型。我所说的一个基本示例是下图:
这就是我如何让我在 Django 中拥有的用户(由 Django 的默认身份验证方案管理django.contrib.auth
)拥有我们想要的其他属性,例如照片、出生日期等。
关于后者,我在下面介绍的方案可能有助于管理我需要的不同用户角色?即患者、医生和物理治疗师
我必须在这些表之间建立关系:
- 医疗用户和患者用户
- 物理治疗师用户和患者用户等在他们和其他表之间
用这种方式,这些关系会不会受到影响?
三种不同类型的用户,他们的属性将存储在 UserProfile 和 User 表之间。
UserProfile 表本身将包含患者、医生和治疗师用户的所有字段。
就可扩展性而言,这是一个好的做法吗?我知道它们当然不会被标准化。
因为另一种选择是考虑我最初的方法,但没有 boolean fields is_patient
,is_medical
然后is_physiotherapist
通过传递性与不同的用户角色一起工作,即像这样:
除了上述之外,还提出了一些替代方案,例如:
- 创建一个名为 Role 的表/模型
如果我有一个单独或独立的角色模型/表,并且这与 Django 用户模型有关,那么我可以说一个用户可以有多个角色。如果我想存储有关特定角色的唯一信息,这种方法会很有用。
Django 权限和授权 目前我不知道粒度的程度(在多大程度上允许我使用模型及其实例进行操作)。
我已经略过授权和权限系统将允许我使用创建、编辑和删除操作
您还可以查看组的创建,例如,一个名为 Doctors 的组,医疗用户属于该组,并且该组(以及组成它的用户)可以对某些模型和操作具有某些权限。其他类型的用户也是如此。
这是另一个不错的选择吗?
- AUTH_USER_MODEL创建自定义用户模型
当 Django 的默认用户管理方案不满足项目中用户身份验证或管理的要求时,另一种选择是替换或自定义用户模型,但我不知道这是否有其缺点保留 Django 通过其用户模型为我们提供的身份验证机制和更多功能。
我对患者用户、医疗用户和物理治疗师用户的要求是否需要构建自定义用户模型?
Django 向我们展示的关于管理用户的一切以及它们允许我们用这个主题做的许多事情本身并不是一件复杂的事情,但从我所看到的和从我的角度来看,我敢肯定它是一个有点广泛的主题,因此,我对根据自己的需要做出最佳决定感到有些困惑。
如果有人做过类似的事情或有任何指导建议(我知道在免费社区中发布它可能是一个非常特殊的情况),我将非常感激。
非常感谢您抽出宝贵的时间并为这篇长文道歉。
我不厌其烦地创建了一个能够塑造你的案例的项目,顺便说一句,我觉得这很有趣,因为我可能会在几个月内遇到类似的项目。
我使用 Django 1.9 创建了这个项目
hospital
(这是我首先想到的)。现在是的,正如开膛手杰克所说,让我们分部分进行。关于您的评论:
在我看来,这让你的事情变得更容易了,你忘记了繁琐的注册,你将创建你的超级用户(使用
createsuperuser
),然后创建必要的系统用户,最重要的是,你(我假设你是系统管理员)您将成为控制谁可以做什么的人。我还假设您不想每次创建用户时都被打扰,因此您会将工具提供给其他权限较少的用户,以便能够创建新患者甚至医生和物理治疗师,就像“超级医生”。请记住,身份验证(用户、密码)和授权(组、权限)是我们必须单独解决的问题。
话虽如此,我们可以从多用户的问题开始。我倾向于使用您的原始想法,扩展 a
User
以具有布尔值并为每种类型处理三种类型的配置文件,我认为当您想要输入授权部分并添加例如用户时,这将更容易处理到组doctor
,fisioterapeuta
或paciente
。每个组都有其权限,并且用户可能属于一个或多个组,因此您可以拥有一位同时也是患者的医生。
现在是的,让我们来看一些代码。我将首先反驳你的说法:
好吧,它不是一成不变的。您可以选择使用AbstractBaseUser 或
AbstractUser
,不同之处在于它AbstractBaseUser
是一个没有 Django 字段的用户,但它包含所有身份验证逻辑,同时它AbstractUser
具有 Django 为您提供的所有字段。然后我们要做的是扩展用户,因为我们不想创建自己的用户模型,但我们想添加一些布尔字段。首先,我们告诉 Django 我们想使用我们自己的用户模型(我创建了一个名为 的应用程序
usuario
):定制模型。不要感觉太糟糕,我使用了与 Django 相同的表名(
auth_user
):然后,Django 本身建议您在扩展用户时要做的第一件事是创建迁移,因此我们运行命令并顺便创建一个超级用户:
通过快速查询,
shell
我们可以看到新字段:如您所见,扩展用户是完全可能的。现在我们需要配置文件。由于配置文件仅与
OneToOne
我们的用户相关,我们可以创建我们想要的所有配置文件(我将为每个配置文件创建几个字段):Nuevamente, creamos la migración y migramos:
Listo, ¡ya replicamos tu idea original!
Autenticación
Veamos si es posible autenticar el usuario. No voy crear todo un login completo, solo haremos uso de
authenticate()
para demostrarlo. Hagámoslo desde elshell
:Perfecto, funciona. Un dolor de cabeza menos, ya sabemos que incluso habiendo creado nuestro propio modelo de usuario heredado del
User
de Django, el proceso de autenticación funciona como debería. La forma en la que haces la autenticación finalmente es tarea tuya (usando el sistema de autenticación Django, OAuth2, Social Auth, etc.).Autorización
Como mencioné anteriormente, bastará por el momento con crear tres grupos:
doctor
,fisioterapeuta
ypaciente
. Antes de continuar, podemos crear algunas funciones en nuestro modeloUser
para obtener los perfiles de acuerdo al tipo de usuario.Esto nos ayudará, ya que cuando usas la relación
OneToOneField
y esta relación no existe, te genera el errorRelatedObjectDoesNotExist
:Pero, si usamos nuestra nuevas funciones, no generará error porque estamos validando previamente que existe el atributo:
Muy bien, entonces estas funciones nos servirán de mucho. Como ejemplo, en alguna de tus vistas podrías usarlas de esta forma para obtener los perfiles de acuerdo al usuario logueado:
Bien, para ver el tema de los grupos, creemos solo un doctor y un paciente: "Dr. House" y "Jorge Enfermizo". No quiero llenar esto de capturas de pantalla ya que esto es fácil de hacer desde el admin, pero hagámoslo desde el
shell
:Listo, ahora creemos los grupos de los usuarios:
Agregamos los usuarios a su grupo correspondiente, digamos que Dr. House también puede ser un paciente:
Ahora, solo bastará con preguntar para saber si un usuario pertenece a cierto grupo, en algunas de tus vistas:
Finalmente, solo quedaría que a los grupos creados, les agregues los permisos que quieres que tenga cada uno y en las vistas uses tus mecanismos para comprobar que el usuario pueda hacer solo lo que su grupo le permite.
Notas finales
Siempre lo digo, no reinventes la rueda a menos que sea por temas didácticos.
Si quieres autenticar usuarios:
Si quieres validar la parte de autorización:
Si se te antoja usar registro de usuarios:
Si quieres un template gratuito, actualizado y muy bueno:
Es muy interesante tu caso de uso, probé una solución un poco mas sencilla, no estoy seguro si cumple a cabalidad con tus requerimientos, en esta solución se puede usar
django.contrib
sin complicaciones para login y demás.Eso sí agregando cada usuario a un grupo de usuarios de Django para posteriores filtros en los views, un usuario puede pertenecer a N grupos sin problemas, desde el sitio de administración puedes asignar a los usuarios a determinados grupos.
Perdón por la informalidad del código, pero es una vista global de como se puede construir la base de datos, los atributos son valores de pruebas.
models.py
Se me viene a la cabeza que la clase
PacienteEspecializado
puede ser una historia clínica o cualquier otra cosa.Al registrarlos en
admin.py
, el código sobra pero bueno.admin.py
Si tienes alguna pregunta o la solución tiene algún error házmelo saber.
Un saludo amigo. Yo uso un enfoque similar al tuyo, creando grupos de usuarios en Groups de Django. Extendiendo el modelo con un modelo "Usuario" y un FK hacia User (Todos mis roles requieren los mismos campos).
Las ultimas funciones aseguran que la creación de un "Usuario" se relacione directamente con la creación de un "User". Lo hice siguiendo este tutorial: https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#onetoone
Otra recomendación es que protejas los templates. No sé que tan recomendable sea puesto que no he hecho protección desde las vistas. Yo he agregado un templatetag en la app usuarios:
Este es el código de user_tags.py:
Luego simplemente la cargas con "load" en tu template. https://docs.djangoproject.com/en/2.1/howto/custom-template-tags/
Ahora, tu app es requerida para un sólo un hospital. Mi problema surgió cuando un usuario tiene varios roles en varias empresas, es decir, es técnico en una y cliente en otra, en ese caso se actualizó el fk hacia empresa, y ahora tiene las reparaciones de la empresa en la que es cliente.
Estoy en este dilema, necesitaría extender la tabla
y añadir empresa_id. Así podría seleccionar a que empresa pertenece el rol en el que se está desempeñando, y al estar los templates protegidos no tendría acceso a ciertas vistas. Espero te sirva y te dejo el enfoque, por si tu app crece y la requieras utilizar en múltiples hospitales, y te evites este quebradero de cabeza en el que estoy.
如果有帮助,请查看本教程:https ://simpleisbetterthancomplex.com/tutorial/2018/01/18/how-to-implement-multiple-user-types-with-django.html
祝你好运和编程!