【问题标题】:Django Multiple User profiles (design decision)Django 多用户配置文件(设计决策)
【发布时间】:2017-11-26 14:02:00
【问题描述】:

标题可能看起来很熟悉(很多相关问题,但我找不到与我的用例相关的问题)。

这是我的应用信息:

  • 两种类型的用户配置文件(基本和专业)
  • 基本用户是 User 的一个实例,带有一个附加字段 (phone)
  • 基本用户发布问题(需要帮助)
  • 专业用户提供各种服务(帮助/回答基本用户发布的问题)
  • 专业用户属于Organisation 类,基本用户不属于。
  • 另外,Pro 代表它自己的组织,所以 Organisation 属于一个配置文件(因此 OneToOneField

问题:所以我需要帮助来决定是为每种类型创建两个单独的配置文件(BasicProfileProProfile),还是创建一个 Profile 并使用一个布尔字段表示个人资料是否is_pro或不是(很像django的is_superuser布尔字段)

方法一:

class Organisation(models.Model):
    name = models.CharField(_('Name'), max_length=50)
    profile = models.OneToOneField(ProProfile, on_delete=models.CASCADE)
    ...

class Profile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    phone = models.CharField(_('Phone'), max_length=200, null=True, blank=True)

    class Meta:
        abstract  = True

    def __str__(self):
        return self.user.get_full_name()

class UserProfile(Profile):
    pass


class ProProfile(Profile):
    verified = models.BooleanField(default=False, verbose_name=_('Verified'))

方法二:

class Organisation(models.Model):
    name = models.CharField(_('Name'), max_length=50)
    profile = models.OneToOneField(Profile, on_delete=models.CASCADE)



class ProfileManager(models.Manager):
    def basic(self, **kwargs):
        return self.filter(is_pro=False, **kwargs)

    def pro(self, **kwargs):
        return self.filter(is_pro=True, **kwargs)


class Profile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    phone = models.CharField(_('Phone'), max_length=200, null=True, blank=True)
    verified = models.BooleanField(default=False, verbose_name=_('Verified'))
    is_pro = models.BooleanField(default=False)

    objects = ProfileManager()

    def __str__(self):
        return self.user.get_full_name()

目前,这些配置文件没有太多功能(字段),但将来可能会获得一些额外的字段。

如果将更多字段/功能添加到用户配置文件中,您个人更喜欢哪种方法更具可读性、可扩展性/可维护性?

一些用例:

p = company.profile(方法二)

p = company.proprofile(约1)

if company.profile.is_pro: # (Appr 2) do_something()

在用户注册时创建配置文件实例,然后:

p = ProProfile.objects.create(user=self.user, phone=phone)
org = form.cleaned_data['org']
Organisation.objects.create(name=org, profile=p) <-- This is simplified version, I do extra validation before creating org)

此外,每种配置文件类型都有自己的仪表板版本。当Pro 登录时,他/她会看到更多内容、基本用户发布的任务列表、组织详细信息、潜在客户等。

编辑:此外,使用方法 1,从 request.user 获取配置文件将是一个命中注定的案例,例如

try:
    request.user.proprofile
    # it's Pro
except RelatedObjectDoesNotExist:
    # it's basic
    pass 

提前致谢。

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    如果我在你身边,我会做以下事情:

    如果基本用户无法成为专业用户:

    在models.py中

    from django.contrib.auth.models import AbstractUser
    
    # create a custom user model
    class User(AbstractUser):
        # declare basic user attributes        
    
        def is_professional(self):
            return hasattr(self, 'pro_user')
    
        def get_profile(self):
            if self.is_professional():
                return self.pro_user
            return self
    
    # create a pro user model
    class ProUser(settings.AUTH_USER_MODEL):
        # declare pro user attributes
    

    然后在settings.py中注册你的用户模型作为默认的认证用户模型:

    AUTH_USER_MODEL = 'main.User'
    

    **每种用户类型必须有不同的注册。

    然后,当您获得用户时,调用 user.get_profile() 将为您提供具有所有属性(“基础”或“专业 + 基础”)的用户实例,具体取决于具体情况。

    如果基本用户可以成为专业用户:

    在models.py中

    # create a custom user model
    class User(AbstractUser):
        # declare basic user attributes        
    
        def is_professional(self):
            return hasattr(self, 'pro_profile')
    
    # create only one profile for pro users
    class ProUserProfile(models.Model):
        user = models.OneToOneField(
            settings.AUTH_USER_MODEL, 
            on_delete=models.CASCADE,
            related_name="pro_profile"
        )
        # declare pro user attributes
    

    然后在settings.py中注册你的用户模型作为默认的认证用户模型:

    AUTH_USER_MODEL = 'main.User'
    

    这样你只有一个用户配置文件,所有用户都将具有基本属性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-27
      • 2012-05-09
      • 2020-02-04
      • 2010-11-09
      • 2011-03-04
      • 2023-03-29
      相关资源
      最近更新 更多