使用Django中的自定义字段扩展用户模型

使用Django中的自定义字段扩展用户模型

Extending the User model with custom fields in Django

使用自定义字段扩展用户模型(与Django的身份验证应用程序捆绑在一起)的最佳方法是什么?我也可能想使用电子邮件作为用户名(用于身份验证)。

我已经看到了一些方法,但无法决定哪一种是最好的。


Django推荐的最不痛苦的方法是通过OneToOneField(User)属性。

Extending the existing User model

If you wish to store information related to User, you can use a one-to-one relationship to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user.

也就是说,扩展EDOCX1[1]并取代它也有效…

Substituting a custom User model

Some kinds of projects may have authentication requirements for which Django’s built-in User model is not always appropriate. For instance, on some sites it makes more sense to use an email address as your identification token instead of a username.

[Ed: Two warnings and a notification follow, mentioning that this is pretty drastic.]

我绝对不会更改Django源代码树中的实际用户类和/或复制和更改auth模块。


注意:此答案已弃用。如果您使用的是django 1.7或更高版本,请参阅其他答案。

我就是这样做的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#in models.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save

class UserProfile(models.Model):  
    user = models.OneToOneField(User)  
    #other fields here

    def __str__(self):  
          return"%s's profile" % self.user  

def create_user_profile(sender, instance, created, **kwargs):  
    if created:  
       profile, created = UserProfile.objects.get_or_create(user=instance)  

post_save.connect(create_user_profile, sender=User)

#in settings.py
AUTH_PROFILE_MODULE = 'YOURAPP.UserProfile'

这将在每次保存用户时创建一个用户配置文件(如果已创建)。然后你可以使用

1
  user.get_profile().whatever

这是从医生那里得到的更多信息

http://docs.djangoproject.com/en/dev/topics/auth/存储有关用户的其他信息

更新:请注意,由于v1.5:https://docs.djangoproject.com/en/1.5/ref/settings/auth profile module,因此不推荐使用AUTH_PROFILE_MODULE


好吧,从2008年以来已经过去了一段时间,现在是时候换个新答案了。自Django1.5以来,您将能够创建自定义用户类。实际上,在我写这个的时候,它已经合并到master中了,所以你可以试试看。

在文档中有一些关于它的信息,或者如果您想深入了解它,在这个提交中。

您所要做的就是将AUTH_USER_MODEL添加到带有自定义用户类路径的设置中,它可以扩展AbstractBaseUser(更可自定义的版本)或AbstractUser(您可以扩展多少个旧的用户类)。

对于那些懒于点击的人,下面是代码示例(取自文档):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)


class MyUserManager(BaseUserManager):
    def create_user(self, email, date_of_birth, password=None):
       """
        Creates and saves a User with the given email, date of
        birth and password.
       """
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=MyUserManager.normalize_email(email),
            date_of_birth=date_of_birth,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, username, date_of_birth, password):
       """
        Creates and saves a superuser with the given email, date of
        birth and password.
       """
        u = self.create_user(username,
                        password=password,
                        date_of_birth=date_of_birth
                    )
        u.is_admin = True
        u.save(using=self._db)
        return u


class MyUser(AbstractBaseUser):
    email = models.EmailField(
                        verbose_name='email address',
                        max_length=255,
                        unique=True,
                    )
    date_of_birth = models.DateField()
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['date_of_birth']

    def get_full_name(self):
        # The user is identified by their email address
        return self.email

    def get_short_name(self):
        # The user is identified by their email address
        return self.email

    def __unicode__(self):
        return self.email

    def has_perm(self, perm, obj=None):
       "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
       "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
       "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin

由于django 1.5,您可以轻松地扩展用户模型并在数据库中保留一个表。

1
2
3
4
5
6
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import ugettext_lazy as _

class UserProfile(AbstractUser):
    age = models.PositiveIntegerField(_("age"))

还必须将其配置为设置文件中的当前用户类

1
2
# supposing you put it in apps/profiles/models.py
AUTH_USER_MODEL ="profiles.UserProfile"

如果你想增加很多用户的偏好,OneTooneField选项可能是一个更好的选择。

开发第三方库的人员注意:如果您需要访问用户类,请记住,用户可以更改它。使用官方助手获得正确的课程

1
2
3
from django.contrib.auth import get_user_model

User = get_user_model()


关于存储有关用户的附加信息,有一个官方建议。Django的书也在章节简介中讨论了这个问题。


下面是扩展用户的另一种方法。我觉得它比上述两种方法更清晰、更容易阅读。

http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/

使用上述方法:

  • 你不需要使用user.get_profile().newattribute访问附加信息与用户相关
  • 您可以直接访问其他新属性通过user.newattribute

  • 每次使用django post save信号创建用户时,只需创建一个新条目即可扩展用户配置文件。

    型号.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    from django.db.models.signals import *
    from __future__ import unicode_literals

    class userProfile(models.Model):

        userName = models.OneToOneField(User, related_name='profile')
        city = models.CharField(max_length=100, null=True)

        def __unicode__(self):  # __str__
            return unicode(self.userName)

    def create_user_profile(sender, instance, created, **kwargs):
        if created:
        userProfile.objects.create(userName=instance)

    post_save.connect(create_user_profile, sender=User)

    这将在创建新用户时自动创建员工实例。

    如果希望扩展用户模型并希望在创建用户时添加更多信息,可以使用django betterforms(http://django betterforms.readthedocs.io/en/latest/multiform.html)。这将创建一个用户添加表单,其中包含在用户配置文件模型中定义的所有字段。

    型号.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from django.db.models.signals import *
    from __future__ import unicode_literals

    class userProfile(models.Model):

        userName = models.OneToOneField(User)
        city = models.CharField(max_length=100)

        def __unicode__(self):  # __str__
            return unicode(self.userName)

    。表格.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    from django import forms
    from django.forms import ModelForm
    from betterforms.multiform import MultiModelForm
    from django.contrib.auth.forms import UserCreationForm
    from .models import *

    class profileForm(ModelForm):

        class Meta:
            model = Employee
            exclude = ('userName',)


    class addUserMultiForm(MultiModelForm):
        form_classes = {
            'user':UserCreationForm,
            'profile':profileForm,
        }

    视图.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    from django.shortcuts import redirect
    from .models import *
    from .forms import *
    from django.views.generic import CreateView

    class addUser(CreateView):
        form_class = addUserMultiForm
        template_name ="addUser.html"
        success_url = '/your url after user created'

        def form_valid(self, form):
            user = form['user'].save()
            profile = form['profile'].save(commit=False)
            profile.userName = User.objects.get(username= user.username)
            profile.save()
            return redirect(self.success_url)

    。添加用户.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            Title
        </head>
        <body>
            <form action="." method="post">
                {% csrf_token %}
                {{ form }}    
                <button type="submit">Add</button>
            </form>
         </body>
    </html>

    号网址.py

    1
    2
    3
    4
    5
    from django.conf.urls import url, include
    from appName.views import *
    urlpatterns = [
            url(r'^add-user/$', addUser.as_view(), name='addDistributor'),
    ]


    像专业人员一样扩展django用户模型(userprofile)

    我发现这个非常有用:链接

    摘录:

    从django.contrib.auth.models导入用户

    1
    2
    3
    4
    5
    6
    class Employee(models.Model):
        user = models.OneToOneField(User)
        department = models.CharField(max_length=100)

    >>> u = User.objects.get(username='fsmith')
    >>> freds_department = u.employee.department


    Django1.5中的新功能,现在您可以创建自己的自定义用户模型(在上述情况下,这似乎是一件好事)。请参阅"在Django中自定义身份验证"

    可能是1.5版本中最酷的新功能。


    这就是我所做的,在我看来,这是最简单的方法。为新的自定义模型定义对象管理器,然后定义模型。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    from django.db import models
    from django.contrib.auth.models import PermissionsMixin, AbstractBaseUser, BaseUserManager

    class User_manager(BaseUserManager):
        def create_user(self, username, email, gender, nickname, password):
            email = self.normalize_email(email)
            user = self.model(username=username, email=email, gender=gender, nickname=nickname)
            user.set_password(password)
            user.save(using=self.db)
            return user

        def create_superuser(self, username, email, gender, password, nickname=None):
            user = self.create_user(username=username, email=email, gender=gender, nickname=nickname, password=password)
            user.is_superuser = True
            user.is_staff = True
            user.save()
            return user



      class User(PermissionsMixin, AbstractBaseUser):
        username = models.CharField(max_length=32, unique=True, )
        email = models.EmailField(max_length=32)
        gender_choices = [("M","Male"), ("F","Female"), ("O","Others")]
        gender = models.CharField(choices=gender_choices, default="M", max_length=1)
        nickname = models.CharField(max_length=32, blank=True, null=True)

        is_active = models.BooleanField(default=True)
        is_staff = models.BooleanField(default=False)
        REQUIRED_FIELDS = ["email","gender"]
        USERNAME_FIELD ="username"
        objects = User_manager()

        def __str__(self):
            return self.username

    不要忘记在您的settings.py中添加这一行代码:

    1
    AUTH_USER_MODEL = 'YourApp.User'

    这就是我所做的,它总是有效的。


    推荐阅读

      linux下用户权限命令?

      linux下用户权限命令?,管理,系统,密码,地址,权限,时间,基础,信息,基本知识,

      linux自定义简写命令?

      linux自定义简写命令?,系统,工作,命令,标准,地址,基础,信息,软件,目录,文件,

      linux命令简写自定义?

      linux命令简写自定义?,系统,状态,命令,代码,工具,发行,标准,软件,文件,别名,L

      linux提取字段串命令?

      linux提取字段串命令?,数字,字符串,状态,工具,命令,文件,范本,样式,正则,字

      linux登陆用户命令?

      linux登陆用户命令?,系统,工具,信息,地址,软件,工作,命令,数字,服务,名称,Lin

      linux用户名改名命令?

      linux用户名改名命令?,系统,密码,命令,代码,名称,用户名,用户,终端,主机名,

      linux磁盘扩展命令?

      linux磁盘扩展命令?,在线,信息,扩大,风险,磁盘,虚拟机,容量,分区,目录,链接,L

      linux用户分组命令?

      linux用户分组命令?,系统,命令,电脑,信息,时间,标准,资料,用户,文件,用户组,L

      linux命令改用户所属?

      linux命令改用户所属?,系统,文件,名称,用户组,命令,用户,名录,基本知识,所

      linux系统用户组命令?

      linux系统用户组命令?,系统,管理,密码,代码,用户组,用户,命令,邮箱,电脑,名

      linux用户管理的命令?

      linux用户管理的命令?,系统,管理,信息,地址,工作,用户,单位,基础,数据,命令,L

      linux用户退出命令行?

      linux用户退出命令行?,状态,档案,标准,系统,命令,文件,模式,编辑,指令,主机,l

      linux用户自定义命令?

      linux用户自定义命令?,系统,时间,标准,软件,项目,电脑,服务,工具,基本知识,

      linux用户组命令设置?

      linux用户组命令设置?,管理,系统,密码,代码,电脑,用户组,用户,软件,新增,命

      linux进入用户命令行?

      linux进入用户命令行?,系统,地址,工作,服务,信息,命令,首页,电脑,密码,终端,L

      linux用户用不了命令?

      linux用户用不了命令?,系统,档案,不了,命令,网络,密码,信息,情况,用户,权限,l

      linux新增用户组命令?

      linux新增用户组命令?,系统,密码,新增,用户组,联系方式,软件,邮箱,工具,管

      linux显示用户名命令?

      linux显示用户名命令?,密码,系统,信息,时间,地址,命令,用户,用户名,位置,用

      linux用户常用命令?

      linux用户常用命令?,工作,地址,系统,信息,管理,目录,命令,标准,基础,常用命

      linux登陆用户的命令?

      linux登陆用户的命令?,系统,密码,工作,用户,命令,代码,第三,信息,分时,用户