在 Django 1.5/1.6 中设置两种不同类型的用户

Posted

技术标签:

【中文标题】在 Django 1.5/1.6 中设置两种不同类型的用户【英文标题】:Setting up two different types of Users in Django 1.5/1.6 【发布时间】:2014-01-13 18:27:35 【问题描述】:

请注意——这是my original question 在此主题上的更新版本,但随着 Django 处理用户和身份验证方式的变化,值得再次询问。

我正在开发一个拥有两种截然不同用户的网站——我们称他们为CustomersStore Owners。两者都在网站上注册,但功能却大不相同。 Customers 只需一个个人资料,就可以在他们喜欢的商店中购物。 Store Owners只有一个账号可以访问多个店铺,每个店铺可以有多个Store Owners

模型的确切细节无关紧要,但这两种类型的用户需要的字段完全不同。理想情况下,模型应如下所示:

Customer
  email (username)
  password
  name
  address
  time_zone
  preferred_shipping
  favorite_stores (many-to-many field)
  ...

Store Owner
  email (username)
  password
  name
  balance
  stores_owned (many-to-many field on Stores)
  stores_managed (many-to-many field on Stores)
  ...

最初,当 Django 对自定义用户的支持很差时,我有一个 UserProfile 类,其中包含一些额外的字段,User 上的 OneToOne,然后是额外的 CustomerStoreOwnerOneToOneUserProfile。这效果不太好。

鉴于 Django 1.5/1.6 中的变化,我正在尝试提出构建它的最佳方法。现在,我有以下内容:

class CustomerUser(AbstractBaseUser):
    ...

class StoreOwnerUser(AbstractBaseUser):
    ...

但是因为会有两种类型的用户,所以我不能将AUTH_USER_MODEL 设置为仅其中一种。

最好的结构是什么,以便我可以拥有具有不同字段的两种不同类型的用户,而不会在用户身份验证、用户创建或管理员方面造成任何问题?

另外,我如何能够仅通过登录来判断此用户是CustomerUser 还是StoreOwnerUser

【问题讨论】:

您可能想要创建一个基本用户,添加一个布尔标志来表示用户是客户还是店主,并附加另一个模型,即配置文件,使用一对一一种关系。 问这个问题已经快一年了,但我发现自己处于类似的情况。问题:你最终采取了什么方法?此外,您是否考虑过店主可能想要注册为客户(使用相同的电子邮件地址)的情况?您的设计如何适应这种情况?最后,您是否考虑过为店主和客户提供单独的登录视图(这有助于轻松区分登录用户类型)? 【参考方案1】:
    创建一个扩展 Django 抽象基本用户的 BaseUser

    创建两个子类 CustomerUser 和 StoreOwnerUser 扩展 BaseUser

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    class BaseUser(AbstractUser):
        # all the common fields go here, for example:
        email = models.EmailField(max_length=10,unique=True)
        name = models.CharField(max_length=120)
    
    class StoreOwnerUser(BaseUser):
        # All Store Owner specific attribute goes here
        balance = models.some_balance_field()
        stores_owned = models.some_stores_owned_field()
    
        class Meta:
        verbose_name = 'Store Owner'
    
    class CustomerUser(BaseUser):
        # All Customer specific attribute goes here
        customer_id = models.CharField(max_length=30, unique=True)
        address =  models.some_address
        time_zone = models.something...
        ...
    
        class Meta:
            verbose_name = 'Customer'
    

【讨论】:

什么会被指定为AUTH_USER_MODEL?登录时也是:user = authenticate(username = username, password = password)authenticate 函数将从哪个表(CustomerUser 或 StoreOwnerUser)检查? 你可以做这个实现***.com/questions/30495979/…【参考方案2】:

最好的结构是什么,这样我就可以有两个 不同类型的用户有不同的领域,不会对我造成任何影响 用户身份验证、用户创建或管理员方面的问题?

您实际上只有一种类型的用户。只是有些用户设置了特定的属性,而其他用户没有。考虑一下 django 是如何拥有“用户”和“管理员”的。它们是相同模型的实例,但具有不同的属性和权限。

您应该以类似的方式处理它。为您的整个应用程序提供一个用户模型。您可以在自定义用户类中设置属性/方法,以识别该用户设置了哪些标志(这将确定用户的“类型”)。

另外,我如何能够仅通过登录来判断该用户是否是 CustomerUserStoreOwnerUser?

您可以使用user_passes_test 装饰器,它接受一个作为函数名称的参数,并且仅当函数返回真值时才会处理视图。

【讨论】:

我非常喜欢这个想法,但是这不会导致我在模型中拥有大量未使用的字段吗?是否有影响,特别是对于表单生成? 不,尤其是如果您正确使用模型的反向关系。例如,您不需要 stores_ownedstores_managed 字段,因为您可以使用 ORM 获取这些信息。例如,您可以在User 中有一个方法,该方法将为“管理的商店”返回self.stores_set.count();如果您要将它作为模型列表视图的一部分显示在管理员中,那么您将在模型中使用该方法,否则它将是某个缓存中的值。【参考方案3】:

您的用户类型似乎有一些共同特征和不常见特征。如果您的用户类型中存在 Django 的默认用户模型不支持开箱即用的常见功能,您应该直接对其进行子类化。

为您的用户类型添加额外的、不常见的功能最好不要通过子类化而是使用配置文件来完成。我这样做的理由是因为您对这些用户类型的身份验证不会从根本上改变,但有关用户的详细信息会根据用户的类型而有所不同。为了适应这一点,您可以使用这些详细信息创建一个单独的模型,并将您的 User 类引用为 OneToOne/ForeignKey 关系(取决于您的设计)。

您可以修改您的用户创建过程以确定它应该是哪种用户类型,并将其关联的 OneToOneField/ForeignKey(取决于您的设计)设置为适当的客户类型模型。

通过这种方式,您应该只有一个 AUTH_USER_MODEL,并且您应该能够处理不同客户类型的详细信息。

【讨论】:

谢谢——这是有道理的。但是我如何从登录中知道登录的用户是StoreOwner 还是Customer?我会在基础UserProfile 类中拥有storeowner_or_customer 字段或类似的字段吗? 类似的东西。 UserProfile 必须对 User 可用,并且这是您每次创建 User 时都要设置的内容。我建议您将两个配置文件模型作为您的两种用户类型(StoreOwner/Customer),然后您可以向您的用户模型添加一个“类型”字段,两个用户类型模型通过 OneToOne 关系引用该字段。在您的代码中,您首先检查类型(即 user_obj.type == "Customer" 或类似的东西),如果为真,您可以直接访问相关详细信息 user_obj.customer.address。

以上是关于在 Django 1.5/1.6 中设置两种不同类型的用户的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Wildfly 中设置两只耳朵的部署顺序

如何使用 Swift 在 iOS 上的 UICollecetionView 中设置两张照片之间的间隔?

Javascript 1.5/1.6 新特性

1.5-1.6 oozie部署

从 Java 中的两个不同类中设置和获取静态变量

jdk 1.5 1.6 1.7 加入新特性