使用 Django 1.5 实现多种用户类型 [英] Implementing multiple user types with Django 1.5

查看:36
本文介绍了使用 Django 1.5 实现多种用户类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Django 1.5 的新可配置的用户模型 功能?

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

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

1) 多表继承

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

将多表继承与可配置用户模型结合使用有什么问题吗?

2) 使用具有类型"属性的单个模型

 类用户(AbstractBaseUser):email = models.EmailField(max_length=254, unique=True)user_type = models.CharField(max_length=30,选择={'P': '私人','T': '贸易',})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 的条件验证.

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

另外,在第 1 种情况下,我该如何过滤我的用户?

谢谢.

解决方案

警告:Django 1.5 非常新,人们仍在研究其新功能.所以我的回答只是我的观点,基于最近回答这个问题的研究.

这两种方式都是实现结果的有效方式,各有利弊.

让我们开始:

第二种选择

  • 没有嵌套模型,也没有模块化.AbstractBaseUser,顾名思义,是一个抽象模型,没有具体的表
  • 有未使用的字段
  • 对于使用额外字段的模型的任何迭代,您都需要检查 user_type:

    def foo():如果 user.user_type == '私人':# ...别的:# ...

生成的 SQL 大致如下:

创建表myapp_user"(id"整数非空主键,密码" varchar(128) 非空,last_login"日期时间非空,"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-like 函数
  • 您无法使用简单的 BaseUser.objects.all()*
  • 访问子类

生成的 SQL 大致如下:

创建表myapp_baseuser"(id"整数非空主键,密码" varchar(128) 非空,last_login"日期时间非空,"email" varchar(254) NOT NULL UNIQUE);创建表myapp_privateuser"(baseuser_ptr_id"整数非空主键引用myapp_baseuser"(id"),"first_name" varchar(30) NOT NULL,"last_name" varchar(30) NOT NULL);创建表myapp_tradeuser"(baseuser_ptr_id"整数非空主键引用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@users.com>]>>>TradeUser.objects.all()[<TradeUser:tradeuser@users.com>]

因此,您不能使用 BaseUser.objects.all() 直接检索子类实例.有一篇优秀的博文Jeff 更好地解释了如何实现从 BaseUser 到它的孩子的自动向下转换".

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

What is the recommended way to implement multiple user types using Django 1.5's new configurable user model functionality?

I would like to have two user types: private users and trade users, each with their own set of required fields.

There are two ways I can think to implement this:

1) Multi-table 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)
  # ...

Are there any problems with using multi-table inheritance in conjunction with the configurable user model?

2) Using a single model with a "type" attribute

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)
  # ...

This method would require some conditional validation dependent upon user_type.

Which of these methods best suits my use case? Or perhaps there is a better way of achieving this?

Also, In case number 1, how can I filter my users?

Thanks.

解决方案

Warning: Django 1.5 is very new and the people are still investigating its new features. So my answer is nothing more than my opinion, based on recent research to answer this question.

Both ways are valid ways to achieve the result, with its advantages and disadvantages.

Let's start with the:

Second option

  • Without nested models and not modular. AbstractBaseUser, as the name says, is an abstract model and does not have a specific table
  • Has unused fields
  • You need to check the user_type for any iteration with the model that uses the extra fields:

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

The resulting SQL would be approximately as follows:

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
);

First option

  • Nested models with logical separation of entities
  • Very lean
  • You must implement BaseUserManager for each child if you want to use create_user-like functions
  • You cannot access the subclasses with a simple BaseUser.objects.all()*

The resulting SQL would be approximately as follows:

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
);

* Imagine the following situation:

>>> 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>]

So, you cannot directly retrieve the subclasses instances by using BaseUser.objects.all(). There is an excellent blog post by Jeff explaining better how to accomplish "automatic downcast" from BaseUser to its childs.

That said, you should consider the advantages and disadvantages of each approach and their impact on your project. When the involved logic is small (as in the example described), both approaches are valid. But in a more complex scenario, an approach can be better than the other one. I would choose the multi model option because it is more extensible.

这篇关于使用 Django 1.5 实现多种用户类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆