有人认为django的用户模型与auth紧密耦合吗?

时间:2010-01-24 02:00:03

标签: django model authentication

我正在尝试学习Django,我希望得到任何拥有MVC / MTV / PHP / Ruby框架经验的人的反馈。有没有人发现用户模型与auth紧密耦合?

背景:当您第一次为Django实现身份验证时,您包含模块django.contrib.auth

这将引入一些模型,如用户,群组,消息等。让我们关注用户模型,因为这是任何网站中最重要的表格之一。

简而言之,User表包含这些字段

用户

  • 用户名max_length 30,唯一,[字母,数字,下划线]
  • 密码max_length 75
  • 电子邮件max_length 75
  • ...以及大约8个其他有用的字段,如first_name,last_name等。

目标:

我想删除用户名并使用电子邮件作为每个用户的登录信息。这是一个非常简单的请求,很多网站都使用这些日子。

我不想修补核心代码,因为这会使升级更加困难。这意味着修改用户模型是不可能的。我只想做一些简单和基本的事情,我希望有一些框架可以做,所以让我来解决Django如何做到这一点。

向用户模型添加新字段

Django docs说使用创建另一个表并在那里插入字段。您将在User表和Profile表之间建立一对一的关系。 例如。 如果要向每个用户添加图像字段,请将其添加到配置文件表中。每次都会进行连接查询。他们甚至指定了一个常量来告诉框架使用哪个表: AUTH_PROFILE_MODULE ='accounts.UserProfile' 我不认为每次我想要一个属于用户表的字段时都必须进行连接查询。

另一种选择是使用add_to_class函数。 django社区已经声明在主类之外定义新字段并不好,因为添加方法的其他开发人员不会知道所有数据成员。

修改旧字段

auth模块检查两个字段的用户名和哈希密码。查看上表,我需要更改用户名模型以接受这些属性。长度为75,包含电子邮件的所有有效字符。 django建议我查看电子邮件字段。

如果我使用电子邮件字段进行身份验证,则会出现两个问题: 我需要编写一个新类,用于常量AUTHENTICATION_BACKEND,因此它会检查电子邮件字段,并且我有一个名为username的未使用字段。

添加新方法

在MVC / MTV中,设计原则是使用胖模型瘦控制器。由于模型是在auth中声明的,我不确定应该如何添加对用户模型字段起作用的方法。由于django建议使用Profile模型,我想他们必须去那里。

扩展用户类

小烦恼是我不能使用“用户”这个名称,而必须使用“用户”或“帐户”。更大的一个是我认为auth不会识别这个新模块。意思是我必须重写一堆存在的功能。这个不会打扰我,因为这是我期望在其他框架中做的事情。

任何评论都表示赞赏。如果我对使用django不感兴趣,我不会问所有这些问题并寻找解决方案。

3 个答案:

答案 0 :(得分:4)

我同意django对auth模型的持续不懈是荒谬的。我的工作要求我创建超可扩展且非常高负载的站点,有时需要用户身份验证,djano的auth模型+权限不适合。

幸运的是,替换并不困难。

首先,创建一个自定义用户模型。

class User(models.Model):
    ...fields...
    #Define some interface methods to be compatible.
    def get_and_delete_messages(self):
    def is_active(self):
    def is_anonymous(self):
    def is_authenticated(self):
    def is_staff(self):
    def has_perm(self, perm_list):

其次,创建自己的身份验证后端。

class LocalAccount(object):
    """
    This checks our local user DB for authentication
    """
    def authenticate(self, username=None, password=None):
        try:
            user = User.objects.get(alias=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None

    def get_user(self, user_id):
        try:
            return User.objects.select_related().get(pk=user_id)
        except User.DoesNotExist:
            return None

#settings.py
AUTHENTICATION_BACKENDS = (
    'helpers.auth.LocalAccount',
)

这应该解决你的大多数问题,我甚至不认为你在django.contrib.auth.User上找到的所有方法都是必要的,我建议你尝试一下。

这里的问题是管理员可能会开始讨厌,幸运的是,使用简单的python继承也很容易修补。这是另一个问题:)

答案 1 :(得分:1)

在一天结束时,您的项目的auth后端需要某种存储来获取身份验证凭据。在这方面,默认 auth后端紧密耦合到User模型并不奇怪。如果您编写自己的身份验证后端({3}},则很容易将自己的定义替换为用户模型。

答案 2 :(得分:0)

我创建了我的Profile模型并使用AUTH_PROFILE_MODULE,所以我可以完全控制我的模型,我可以修改字段,添加方法等等。现在我正在考虑使用缓存和编写中间件,如果可能的话,将从缓存中获取配置文件

要使用电子邮件登录,您可以编写非常简单的身份验证后端:

from django.contrib.auth.models import User
from django.contrib.auth.backends import ModelBackend

class EmailModelBackend(ModelBackend):
    def authenticate(self, username=None, password=None):
        try:
            user = User.objects.get(email=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None