用Django 1.5实现多个用户types

使用Django 1.5新的可configuration用户模型function实现多种用户types的推荐方法是什么?

我想有两种用户types:私人用户和交易用户,每个用户都有自己的一组必填字段。

有两种方法可以实现这一点:

1)多表inheritance

class BaseUser(AbstractBaseUser): email = models.EmailField(max_length=254, unique=True) # ... class PrivateUser(BaseUser): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) # ... class TradeUser(BaseUser): company_name = models.CharField(max_length=100) # ... 

将多表inheritance与可configuration的用户模型结合使用会有什么问题吗?

2)使用具有“type”属性的单个模型

 class User(AbstractBaseUser): email = models.EmailField(max_length=254, unique=True) user_type = models.CharField(max_length=30, choices={ 'P': 'Private', 'T': 'Trade', }) first_name = models.CharField(max_length=30, blank=True) last_name = models.CharField(max_length=30, blank=True) company_name = models.CharField(max_length=100, blank=True) # ... 

这个方法需要一些依赖于user_type条件validation。

哪种方法最适合我的用例? 或者也许有更好的方法来实现这一目标?

此外,在案件号码1,我如何过滤我的用户?

谢谢。

警告:Django 1.5是非常新的,人们仍在研究其新function。 所以我的回答只不过是根据最近的研究来回答这个问题。

两种方式都是取得成效的有效方式,有其优缺点。

我们从下面开始:

第二个选项

  • 没有嵌套模型而不是模块化。 AbstractBaseUser正如名称所示,是一个抽象模型,没有特定的表格
  • 有未使用的字段
  • 您需要检查user_type与使用额外字段的模型的任何迭代:

     def foo(): if user.user_type == 'Private': # ... else: # ... 

生成的SQL大致如下所示:

 CREATE TABLE "myapp_user" ( "id" integer NOT NULL PRIMARY KEY, "password" varchar(128) NOT NULL, "last_login" datetime NOT NULL, "email" varchar(254) NOT NULL UNIQUE, "user_type" varchar(30) NOT NULL, "first_name" varchar(30) NOT NULL, "last_name" varchar(30) NOT NULL, "company_name" varchar(100) NOT NULL ); 

第一个选项

  • 与逻辑分离实体的嵌套模型
  • 非常精益
  • 如果要使用 BaseUserManager create_user的函数, 必须为每个子项实现BaseUserManager
  • 你不能用一个简单的BaseUser.objects.all()来访问这个子类

生成的SQL大致如下所示:

 CREATE TABLE "myapp_baseuser" ( "id" integer NOT NULL PRIMARY KEY, "password" varchar(128) NOT NULL, "last_login" datetime NOT NULL, "email" varchar(254) NOT NULL UNIQUE ); CREATE TABLE "myapp_privateuser" ( "baseuser_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "myapp_baseuser" ("id"), "first_name" varchar(30) NOT NULL, "last_name" varchar(30) NOT NULL ); CREATE TABLE "myapp_tradeuser" ( "baseuser_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "myapp_baseuser" ("id"), "company_name" varchar(100) NOT NULL ); 

*想象一下以下情况:

 >>> BaseUser.objects.create_user('baseuser@users.com', password='baseuser') >>> PrivateUser.objects.create_user('privateuser@users.com', password='privateuser', first_name='His', last_name='Name') >>> TradeUser.objects.create_user('tradeuser@users.com', password='tradeuser', company_name='Tech Inc.') >>> BaseUser.objects.all() [<BaseUser: baseuser@users.com>, <BaseUser: privateuser@users.com>, <BaseUser: tradeuser@users.com>] >>> PrivateUser.objects.all() [<PrivateUser: privateuser@users.com>] >>> TradeUser.objects.all() [<TradeUser: tradeuser@users.com>] 

因此,您不能通过使用BaseUser.objects.all()直接检索子类实例。 杰夫有一篇很好的博客文章解释了如何完成从BaseUser到其BaseUser “自动BaseUser ”。

也就是说,您应该考虑每种方法的优缺点及其对您项目的影响。 当所涉及的逻辑很小(如在所描述的例子中),两种方法都是有效的。 但在更复杂的情况下,一种方法可能比另一种更好。 我会select多模型选项,因为它更具可扩展性。

也许你应该考虑AbstractUser?

新的自定义用户模型只能将一个模型分配给AUTH_USER_MODEL。 多表inheritance有两种模式。 所以这是一个问题。

在涵盖两种用户types的单用户模型的情况下,您可以抽象模型方法中的条件逻辑。 您也可以根据用户types的不同,为不同的用户types使用不同的pipe理员。 这也可以帮助您在使用特定用户types时进行显式指定。

其他选项可能是仅将最常见的属性存储在单个用户模型中,然后将两个用户types的具体信息附加到与主用户表链接的表中。

如果两个用户都拥有大部分的共同点(至less在数据方面),我会把它们放在一个地方。 最后,我会考虑更简单,更容易维护的事情。

我会使用一个“type”属性的单一模型。 这是为什么:

  • 只有一个表,只有一个模型
  • 如果你想从一种types转换到另一种,你只需要改变属性
  • 为一个types存在的字段实现getter和setter,并且不为其他types存在=更简单易用。