django - 有人认为 django 的用户模型与身份验证耦合得太紧了吗?

标签 django model authentication

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

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

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

简而言之,用户表有这些字段

用户

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

  • 目标:

    我想删除用户名并使用电子邮件作为每个用户的登录名。这是当今许多网站使用的一个非常简单的请求。

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

    向用户模型中添加新字段

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

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

    编辑旧字段

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

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

    添加新方法

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

    扩展用户类

    一个小烦恼是我不能使用名称“用户”,而必须使用“用户”或“帐户”。更大的一个是我认为身份验证不会识别这个新模块。这意味着我将不得不重写现有的一堆功能。这个不会打扰我,因为这是我希望在其他框架中做的事情。

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

    最佳答案

    我同意 django 对 auth 模型的不断依附是荒谬的。我的工作要求我创建超可扩展且负载非常高的站点,这些站点有时需要用户身份验证,而 djano 的身份验证模型 + 权限不符合此要求。

    幸运的是,更换并不难。

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

    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 继承也很容易修补。这是另一个问题:)

    关于django - 有人认为 django 的用户模型与身份验证耦合得太紧了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2125588/

    相关文章:

    node.js - nodejs Passport 身份验证 token

    django 3在表单验证中使用pk重定向

    python - “没有为[过滤]注册[查询]”

    sql - 使用模型关联查找

    c++ - Simulink Coder - 如何将外部代码与模型连接起来

    java - 注册后自动登录

    android - 为什么 Gallery 如此缓慢/访问 GoogleLoginService?

    python - Django 和 Sqlite 并发问题

    python - Django:不允许用户在未登录时查看页面

    Java Swing : Jtable with many models and custom renderer