代码之家  ›  专栏  ›  技术社区  ›  Art

在django中使用电子邮件而不是登录名

  •  7
  • Art  · 技术社区  · 16 年前

    我想在一个给定的django项目中使用电子邮件作为用户名。但是,我无法重用auth.User model提供的字段,至少有两个原因:

    1. auth.User.username的字段最大长度为30个字符,这对于某些电子邮件地址来说可能不够。

    所以这里一个明显的方法是将用户名存储在一个自定义配置文件中,该配置文件链接到auth.User。在这种情况下,我们必须处理以下问题:

    1. What is the maximum length of a valid email address? )电子邮件可以长达256个字符。

    以下问题源于建议的解决方案:

    1. 如果电子邮件更改,则必须更新auth.User.username

    http://code.djangoproject.com/ticket/11365

    所以问题是:有没有其他的方法可以做到这一点?你认为在上面提出的解决方案中还有其他的缺点吗?

    谢谢!

    7 回复  |  直到 9 年前
        1
  •  5
  •   Peter Rowell    16 年前

    我有一个客户有一个商业网站,从1995年就开始了(是的,我们在这里讨论的是早期采用者)。不管怎样,他们已经有了一个固定的用户群 完全地 不符合Django的用户名概念。

    这并不漂亮,我可能会因为这样做而被烧死,但这样做所花的时间比我能想到的任何事情都要少,而且转发端口完全没有问题。

        3
  •  1
  •   Micah Carrick    15 年前

    我写了一篇关于我解决这个问题的解释: Django Authentication using an Email Address . 它主要包括:

    • 为电子邮件身份验证创建自定义授权后端。
    • 子类化用户创建表单以将电子邮件地址添加为必需字段。
    • 在创建和登录表单中对用户隐藏用户名字段。

        4
  •  0
  •   Filip Dupanović    16 年前

    我也必须承认我会在地狱里被烧死。我最近部署了一个小应用程序,我在其中删除了用户的电子邮件,将其切成30个字符,并将其设置为用户名。我想 就这么过去了。写了几行代码,瞧。

    通常

        5
  •  0
  •   Dominique Guardiola    15 年前

    我只是用 this djangosnippet 用户可以使用自己的用户名或电子邮件。
    但它不能解决75个字符的限制,只是一个方便的片段。

        6
  •  0
  •   Adrian Lopez    11 年前

    我写了一个基于Dominique answer的解决方案,其中包括安全改进和一些额外的功能,比如区分大小写的身份验证。如果你愿意,你可以 install it directly from pypi :

    from django.contrib.auth.backends import ModelBackend
    from django.contrib.auth import get_user_model
    from django.conf import settings
    
    ###################################
    """  DEFAULT SETTINGS + ALIAS   """
    ###################################
    
    
    try:
        am = settings.AUTHENTICATION_METHOD
    except:
        am = 'both'
    try:
        cs = settings.AUTHENTICATION_CASE_SENSITIVE
    except:
        cs = 'both'
    
    #####################
    """   EXCEPTIONS  """
    #####################
    
    
    VALID_AM = ['username', 'email', 'both']
    VALID_CS = ['username', 'email', 'both', 'none']
    
    if (am not in VALID_AM):
        raise Exception("Invalid value for AUTHENTICATION_METHOD in project "
                        "settings. Use 'username','email', or 'both'.")
    
    if (cs not in VALID_CS):
        raise Exception("Invalid value for AUTHENTICATION_CASE_SENSITIVE in project "
                        "settings. Use 'username','email', 'both' or 'none'.")
    
    ############################
    """  OVERRIDDEN METHODS  """
    ############################
    
    
    class DualAuthentication(ModelBackend):
        """
        This is a ModelBacked that allows authentication
        with either a username or an email address.
        """
    
        def authenticate(self, username=None, password=None):
            UserModel = get_user_model()
            try:
                if ((am == 'email') or (am == 'both')):
                    if ((cs == 'email') or cs == 'both'):
                        kwargs = {'email': username}
                    else:
                        kwargs = {'email__iexact': username}
    
                    user = UserModel.objects.get(**kwargs)
                else:
                    raise
            except:
                if ((am == 'username') or (am == 'both')):
                    if ((cs == 'username') or cs == 'both'):
                        kwargs = {'username': username}
                    else:
                    kwargs = {'username__iexact': username}
    
                    user = UserModel.objects.get(**kwargs)
            finally:
                try:
                    if user.check_password(password):
                        return user
                except:
                    # Run the default password hasher once to reduce the timing
                    # difference between an existing and a non-existing user.
                    UserModel().set_password(password)
                    return None
    
        def get_user(self, username):
            UserModel = get_user_model()
            try:
                return UserModel.objects.get(pk=username)
            except UserModel.DoesNotExist:
                return None