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

时间:2013-12-26 04:20:23

标签: python django django-models django-users django-1.6

请注意 - 这是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类,其中包含一些OneToOne User的其他字段,然后是Customer和{在StoreOwnerOneToOne的{​​1}}类。这不是很好。

鉴于Django 1.5 / 1.6的变化,我试图想出最好的结构方法。现在,我有以下内容:

UserProfile

但是因为会有两种类型的用户,我无法将class CustomerUser(AbstractBaseUser): ... class StoreOwnerUser(AbstractBaseUser): ... 设置为只有其中一种。

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

此外,我如何能够从登录单独判断此用户是AUTH_USER_MODEL还是CustomerUser

3 个答案:

答案 0 :(得分:5)

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

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

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

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

答案 1 :(得分:3)

  

最好的结构方法是什么,这样才能有两个   不同类型的用户使用不同的字段,而不会导致任何问题   用户身份验证,用户创建或管理员的问题?

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

你应该同样接近它。为整个应用程序提供一个用户模型。您可以在自定义用户类中设置属性/方法,以标识此用户设置的标志(这将决定用户的“类型”)。

  

此外,我如何能够从登录单独判断此用户是否是   CustomerUserStoreOwnerUser

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

答案 2 :(得分:1)

  1. 创建一个扩展Django的抽象基础用户的BaseUser
  2. 创建两个名为CustomerUser的子类和扩展BaseUser的StoreOwnerUser

    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'