11

请注意——这是我关于这个主题的原始问题的更新版本,但随着 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类,其中包含一些带有OneToOneon的附加字段User,然后是on的附加CustomerStoreOwner类。这不是很好。OneToOneUserProfile

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

class CustomerUser(AbstractBaseUser):
    ...

class StoreOwnerUser(AbstractBaseUser):
    ...

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

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

另外,我如何能够单独从登录中判断该用户是 aCustomerUser还是 a StoreOwnerUser

4

3 回答 3

5

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

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

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

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

于 2013-12-26T04:29:26.940 回答
3

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

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

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

另外,我如何能够单独从登录中判断该用户是 aCustomerUser还是 a StoreOwnerUser

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

于 2013-12-26T04:38:44.600 回答
1
  1. 创建一个扩展 Django 抽象基本用户的 BaseUser
  2. 创建两个名为 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'
    
于 2015-08-07T08:30:34.030 回答