Django 上的用户角色架构

User roles schema on Django

一个很棒的问候社区

我的问题与 Django 中管理用户和模式用户的类型有关,首先我向您道歉,以防我的问题太过 "newbies" 或没有意义,我是开始将我与 Django 用户模式及其在项目中的不同工作可能性联系起来。

我有以下情况。

我正在构建一个应用程序,我将在其中拥有三种不同的用户类型:

我正在使用默认的 Django 身份验证方案 (django.contrib.auth)。

最初,我确实认为在这种实体方案中,用户 table 是 auth_user table 在 Django 中保存用户创建的位置:

我有 is_patientis_medicalis_physiotherapist 字段,例如用户 table 中的布尔属性。

像一个特定的细节,我了解到在 Django 默认模型中,用户不可能修改或添加属性或字段。

这是我无法在用户 table.

中添加 is_patientis_medicalis_physiotherapist 布尔字段的一个重要而有力的原因

一个经典的建议是使用 Userprofile table 扩展 User 模型,在其中我通过 OneToOne 关系向 User 模型添加字段或属性。基本示例如下:

通过这种方式,我可以让我在 Django 中的用户拥有现场照片并在给定时刻上传一张...

趁着前面的优势, 以下模式适合或可以替代管理用户角色(patientmedicalphysiotherapist 用户类型)?

我将有以下关系:

他们和其他 table 之间等等...

采用这种方法,这些关系不会受到影响吗?

Users 和 UserProfile 之间将保存不同的用户 table。 从可扩展性的角度来看,这是一个好的做法吗?我的 table 可能崩溃或我的数据库?


此外,我还看到了其他替代方案,例如:

  1. 角色Table/Model

我将有一个 table/model 独立或独立的角色,这可以与 Django 用户模型相关(例如,一个用户可以有多个角色) 当我想在 specia 中存储有关某个角色的独有信息时,这种方法很有用?

  1. Django Permissions and Authorization

我忽略或不知道让我工作的粒度等级。我已经看到权限和授权系统让我以一种方式进行创建、编辑和删除操作....

在这里,我可以看到创建的群组吗? 例如医疗组并为他们分配权限并将此权限链接到组成该组的用户?这是另一个好的选择吗? 这个选项看起来比较单一,虽然我不知道用户是否可以根据具有的组权限进行一些操作......我不知道这个想法是否correct/right

  1. AUTH_USER_MODEL Creating a Custom User model

我对患者、医疗和物理治疗师用户的要求,需要构建自定义用户模型吗?

您可以创建或不创建自定义用户模型,在任何情况下,您都可以拥有三个单独的模型来存储相关数据,具体取决于用户是患者、医生、物理治疗师还是这些的任意组合。

如果您的权限方案仅由角色(患者、医生、物理治疗师)决定,那么您不需要使用 Django 的权限系统,因为您知道任何用户的角色,并且您可以,最坏的情况,硬编码授权规则。

在这种情况下,特别是如果您想为患者、医生和物理治疗师存储不同的信息,您可以为每个人创建一个模型,并为每个人的用户模型创建一个 OneToOne 字段。

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

通过这种方式,您可以在您的应用程序逻辑中为每种类型的用户隐式地提供不同的 permissions/roles(并且如果您在特殊情况下需要它们,仍然可以使用 Django 提供的组和权限,例如 ChiefMedical... ).

您必须为您的应用程序逻辑定义一些方法,例如

def user_is_patient(user):
     ...

如果您遵循此路径,最好进行良好的测试以确保您不会遇到意外情况,例如用户是 Medic 和 Physio...

Django 还允许您对用户模型进行子类化。在幕后它会做与上面代码相​​同的事情,所以最好像上面所示那样明确地做它(这样你访问那个对象中不存在的属性的可能性就会降低!)

Taking advantage of the previous, The following schema can be suited or can be an alternative for manage user roles (patient, medical and physiotherapist user types) ?

您显示的架构不是很好,因为它让您将所有用户类型的信息存储在相同的 table(并且具有相同的字段)中。例如,Medics 和 Physios 将有一个血型字段类型,如 Patients,它可能不会被定义。

The different users will be saved between the Users and UserProfile table. Is this a good practice in the scalability sense? My tables could be crash or my database?

此解决方案应该没有可伸缩性问题(只要您没有每天写入数百万个新条目)并且您始终可以在进一步优化数据库。但是,您必须确保您的应用不接受 'forbidden' 条目(例如没有 Medic、Physio 或 Patient 资料的用户)

Here, can I see the groups creation? For example a medical group and allocate them permissions and linked this permissions to the users that compose the group ? Is this another good alternative? This option seem more single although I don't know if an user could make some operations according to the group privileges that have ... I don't know if this thinking is correct/right

您可以(应该)使用 Django 的权限系统来为您的用户授予权限。您可以使用它们为同一类型的用户授予不同的权限(例如,拥有比其他人更多权限的医生......或者拥有首席理疗师组......)

Django 允许您为组分配权限。

但我不认为组可以替换每个用户的自定义模型,因为您想为他们存储信息。拥有自定义模型和组将是多余的,并且会使您的应用程序更难维护。

My requirements for patient, medical and physiotherapist users, require build a custom user model?

这个选项不是很好(除非它是您唯一的选择),因为您的应用程序将无法重复使用,并且您可能还会遇到某些软件包的问题。

我看了一眼问题的评论,我看到了一些问题:

()

我意识到你的用户模型与原始数据模型不匹配,因为在用户模型中有 get_medical_profileget_patient_profileget_physiotherapist_profile 函数,你假设任何用户可以同时拥有多个个人资料,这既不会反映在您使用 OneToOneField 的个人资料模型(医疗、患者和物理治疗师)中,也不会反映在问题的原始数据模型中,这是关于抽象的重要事情 class -责任。要求(根据下面的模型)似乎是 "one user can have only one profile".

所以..我认为这可以通过一种简单明了的方式解决,您不需要参与整体身份验证 esquema,如组和权限或向用户模型添加其他属性:

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

如您所见,您可以拥有一个配置文件,其中包含所有配置文件共享的公共字段。每个配置文件都有一个特定的模型。

此外,您可以通过下面这个小功能检查用户是否医疗,如果没有与个人资料关联的医疗资料,那么它会引发异常,这意味着它是一个未指定的个人资料:

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

您也可以通过这种方式在您的模板中使用它(作为自定义模板标签):

{% if profile | is_medical_profile %}

使用这种方法你不需要设置AUTH_USER_MODEL

我希望这会改进您的解决方案。


补充说明:

以防万一您决定拥有自定义用户模型,设置 settings.AUTH_USER_MODEL 并将其用于用户的外键。

在很棒的书的一段文字上 Two scoops of Django 说:

From Django 1.5 onwards, the official preferred way to attach ForeignKey, OneToOneField, or ManyToManyField to User

因此,您的用户配置文件模型将更改如下:

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

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

是的,它看起来有点奇怪,但这是 Django 官方文档的建议。

@geoom @Ire @lorenzo-peña 我通过 Django 管理站点创建了一个用户,并通过 [=] 检查了他们的属性(is_medical、is_patient、is_physiotherapist) 27=]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}]

目前,在我的 views.py 中,只有当用户属于三种用户类型(医疗、患者或物理治疗师)之一时,我才会登录

# 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

如果我检查其他可能的组合(用户患者、医生和物理治疗师)这可行吗?

我想为(医生、患者、物理治疗师)创建组并为授权主题绑定用户,尽管我应该审查授权过程的其他事情,例如 django guardian

这个怎么样?