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

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

问题描述

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



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



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



1)多表继承



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

使用多表继承与conf可用的用户模型?



2)使用具有type属性的单一模型



 code> 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)
#...
/ pre>

此方法需要一些取决于 user_type 的条件验证。



哪些方法最适合我的用例?或者也许有更好的方式实现这一点?



另外,如果第1号,如何过滤我的用户?



谢谢。

解决方案

警告:Django 1.5是非常新的,人们还在调查其新功能。所以我的答案只不过是我最近根据最近的研究回答这个问题的看法。



这两种方法都是有效的方式来实现结果,其优点和缺点。开始于:



第二个选项




  • 没有嵌套模型而不是模块化。 AbstractBaseUser ,正如名称所示,是一个抽象模型,没有特定的表

  • 没有未使用的字段

  • 您需要使用使用额外字段的模型来检查user_type是否为任何重复:

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




生成的SQL大致如下:

  CREATE TABLEmyapp_user(
idinteger NOT NULL PRIMARY KEY,
passwordvarchar(128)NOT NULL,
last_logindatetime NOT NULL,
emailvarchar(254)NOT NULL UNIQUE,
user_typevarchar(30)NOT NULL,
first_namevarchar(30) NOT NULL,
last_namevarchar(30)NOT NULL,
company_namevarchar(100)NOT NULL
);

第一个选项




  • 具有逻辑分离实体的嵌套模型

  • 非常精益

  • 您必须实现 BaseUserManager 对于每个小孩如果要使用 create_user 类功能

  • 您无法使用简单的 BaseUser.objects.all() *



生成的SQL大致如下:

  CREATE TABLEmyapp_baseuser(
idinteger NOT NULL PRIMARY KEY
passwordvarchar(128)NOT NULL,
last_logindatetime NOT NULL,
emailvarchar(254)NOT NULL UNIQUE
);

CREATE TABLEmyapp_privateuser(
baseuser_ptr_idinteger NOT NULL主键参考myapp_baseuser(id),
first_namevarchar(30)NOT NULL,
last_namevarchar(30)NOT NULL
);

CREATE TABLEmyapp_tradeuser(
baseuser_ptr_idinteger NOT NULL主键参考myapp_baseuser(id),
company_namevarchar(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()直接检索子类实例。有一个优秀的博文通过Jeff更好地解释如何从 BaseUser 完成自动downcast到它的孩子。



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


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天全站免登陆