一个很棒的问候社区
我的问题与Django中的管理用户和架构用户的类型有关,一开始我请你道歉,以防万一我的问题也可能会出现问题"新手"或者没有意义,我开始将我与Django用户模式及其在项目中的不同工作可能性联系起来。
我有以下情况。
我正在构建一个应用程序,其中我将有三种不同的用户类型:
我正在使用默认的Django身份验证方案(django.contrib.auth)。
最初,我确实在这个实体方案中考虑过,其中User表是Django保存用户创建的auth_user
表:
我在User表中有is_patient
,is_medical
和is_physiotherapist
字段,如布尔属性。
像特定细节一样,我理解在Django默认模型中,用户无法修改或添加属性或字段。
这是一个重要且有力的理由,我无法在用户表中添加is_patient
,is_medical
和is_physiotherapist
布尔字段。
经典建议是使用Userprofile表扩展User模型,在该表中我通过OneToOne关系向User Model添加字段或属性。基本样本如下:
通过这种方式,我得到了Django中的用户可以拥有现场照片并在特定时刻上传一个......
利用以前的,
以下架构适合或可以替代管理用户角色(patient
,medical
和physiotherapist
用户类型)?
我将在:
之间建立关系用户医疗和用户患者
用户物理治疗师和用户患者
等他们和其他桌子......
通过这种方法,这些关系不会受到影响吗?
将在Users和UserProfile表之间保存不同的用户。 这是可扩展性意义上的一个好习惯吗?我的表可能是崩溃还是我的数据库?
此外,我还看到了其他替代方案,例如:
我将使角色表/模型独立或分离,并且这可以与Django用户模型相关(一个用户可以通过示例具有多个角色) 当我想要在specia中存储关于角色的独家信息时,这种方法很有用吗?
我忽略或不知道让我工作的粒度等级。我只看到权限和授权系统允许我使用创建,编辑和删除操作......
在这里,我可以看到群组创作吗? 例如,医疗组并为其分配权限并将此权限链接到组成该组的用户?这是另一个好的选择吗? 这个选项似乎更单一,但我不知道用户是否可以根据群组权限进行某些操作......我不知道这种想法是否正确/正确
我对患者,医疗和物理治疗师用户的要求需要构建自定义用户模型吗?
答案 0 :(得分:6)
在这种情况下,特别是如果您想为患者,医务人员和物理治疗师存储不同的信息,您可以为每个人创建一个模型,并为每个用户模型设置一个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
通过这种方式,您可以在应用程序逻辑中为每种类型的用户隐式提供不同的权限/角色(并且仍然使用Django提供的组和权限,如果您需要特殊情况,例如ChiefMedical ......)。
您必须为您的应用程序逻辑定义一些方法,例如
def user_is_patient(user):
...
如果您遵循这条路径,最好进行良好的测试,以确保您不会遇到意外的事情,例如Medic和Physio的用户......
Django也允许您为用户模型创建子类。在封面下,它将与上面的代码做同样的事情,因此最好如上所示明确地执行此操作(这样,您访问该对象中不存在的属性的可能性就会降低!)< / p>
利用以前的模式,以下模式可以适用于管理用户角色(患者,医疗和物理治疗师用户类型),也可以作为替代方案?
您展示的架构并不是很好,因为它可以让您将所有用户类型的信息存储在同一个表中(并使用相同的字段)。例如,Medics和Physios将具有类似患者的血型字段类型,可能无法定义。
将在Users和UserProfile表之间保存不同的用户。这是可扩展性意义上的一个好习惯吗?我的表可能是崩溃还是我的数据库?
此解决方案不应存在可伸缩性问题(只要您每天都没有数百万条新条目写入),您可以随时优化数据库。但是,您必须确保您的应用无法接受“禁止”#39;条目(例如没有Medic,Physio或Patient个人资料的用户)
在这里,我可以看到群组创作吗?例如,医疗组并为其分配权限并将此权限链接到组成该组的用户?这是另一个好的选择吗?这个选项似乎更单一,但我不知道用户是否可以根据群组权限进行某些操作......我不知道这种想法是否正确/正确
您可以(应该)使用Django的权限系统为您的用户授予权限。您可以使用它们为相同类型的用户提供不同的权限(例如,具有比其他用户更多权限的Medics ......或者具有主要物理组的用户......)
Django允许您为组分配权限。
但我不认为群组可以替换每个用户的自定义模型,因为您希望为它们存储信息。拥有自定义模型和组将是多余的,并使您的应用程序更难维护。
我对患者,医疗和物理治疗师用户的要求需要构建自定义用户模型吗?
此选项不会很好(除非它是您唯一的选择),因为您的应用程序不会重复使用,并且您可能也遇到某些程序包的问题。
答案 1 :(得分:3)
您可以创建或不创建自定义用户模型,在任何情况下,您可以使用三个单独的模型来存储相关数据,具体取决于用户是患者,医疗,物理治疗师还是这些模型的任意组合。
如果您的权限方案完全由角色(患者,医疗,物理治疗师)决定,那么您不需要使用Django的权限系统,因为您知道任何用户的角色和在最糟糕的情况下,您可以使用硬编码授权规则。
答案 2 :(得分:2)
我瞥了一眼问题的评论,我看了一些问题:
我意识到您的用户模型与原始数据模型不匹配,因为在用户模型中有get_medical_profile
,get_patient_profile
和get_physiotherapist_profile
函数,您假设任何用户都可以同时拥有多个配置文件,这些配置文件(医疗,患者和物理治疗师)既没有使用OneToOneField,也没有反映在问题的原始数据模型中,这对抽象和类责任来说非常重要。要求(根据下面的模型)似乎说“一个用户只能有一个配置文件”。
所以......我认为这可以通过简单明了的方式解决,您不需要像组和权限那样参与整体身份验证,也不需要为用户模型添加其他属性:
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上写道:
从Django 1.5开始,这是官方首选的附加方式 ForeignKey,OneToOneField或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文档的建议。
答案 3 :(得分:0)
@geoom @Ire @ lorenzo-peña我通过Django管理站点创建了一个用户,我通过python shell检查了他们的属性(is_medical,is_patient,is_physiotherapist)
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?
这个怎么样?