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

在Django中使用自定义字段扩展用户模型,django,django-models,django-authentication,django-users,Django,Django Models,Django Authentication,Django Users,使用自定义字段扩展用户模型(与Django的身份验证应用程序捆绑)的最佳方法是什么?我也可能希望使用电子邮件作为用户名(用于身份验证) 我已经看到了一个解决方案,但无法决定哪一个是最好的。有一个官方的建议。 Django的书在第节中也讨论了这个问题。Django推荐的最不痛苦的方法是通过OneToOneField(User)属性 如果您希望存储与用户相关的信息,则可以使用到包含附加信息字段的模型。此一对一模型通常称为概要文件模型,因为它可能存储有关站点用户的非身份验证相关信息 也就是说,扩展d

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


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

有一个官方的建议。
Django的书在第节中也讨论了这个问题。

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

如果您希望存储与
用户相关的信息
,则可以使用到包含附加信息字段的模型。此一对一模型通常称为概要文件模型,因为它可能存储有关站点用户的非身份验证相关信息

也就是说,扩展django.contrib.auth.models.User并替换它同样有效

某些类型的项目可能有身份验证需求,Django内置的
用户
模型并不总是适合这些需求。例如,在某些网站上,使用电子邮件地址作为身份标识而不是用户名更有意义

[Ed:紧接着两次警告和一次通知,提到这是非常激烈的]


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

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

使用上述方法:

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

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

    我就是这样做的

    #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'
    
    这将在每次保存用户(如果已创建)时创建用户配置文件。 然后您可以使用

      user.get_profile().whatever
    
    这里是来自文档的更多信息


    更新:请注意,
    AUTH\u PROFILE\u模块
    从v1.5开始就被弃用了:

    好吧,2008年已经过去了一段时间,是时候给出一些新的答案了。自Django 1.5以来,您将能够创建自定义用户类。实际上,在我写这篇文章的时候,它已经合并到master中,所以你可以试试

    在中有一些关于它的信息,或者如果你想深入研究,请在中

    您所要做的就是将
    AUTH\u USER\u MODEL
    添加到带有自定义用户类路径的设置中,该设置扩展了
    AbstractBaseUser
    (更可自定义的版本)或
    AbstractUser
    (您可以扩展更多或更少的旧用户类)

    对于懒于点击的人,下面是代码示例(摘自):


    Django 1.5中的新功能,现在您可以创建自己的自定义用户模型(在上述情况下,这似乎是一件好事)。指


    可能是1.5版上最酷的新功能。

    自Django 1.5以来,您可以轻松扩展用户模型并在数据库中保留一个表

    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"))
    
    您还必须在设置文件中将其配置为当前用户类

    # supposing you put it in apps/profiles/models.py
    AUTH_USER_MODEL = "profiles.UserProfile"
    
    如果您想添加许多用户的首选项,OneToOneField选项可能是一个更好的选择

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

    from django.contrib.auth import get_user_model
    
    User = get_user_model()
    

    像Pro一样扩展Django用户模型(UserProfile)

    我发现这非常有用:

    摘录:

    from django.contrib.auth.models import User
    
    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
    

    您可以通过每次使用Django post save信号创建用户时创建一个新条目来扩展用户配置文件

    models.py 这将在创建新用户时自动创建employee实例

    如果您希望扩展用户模型并希望在创建用户时添加更多信息,则可以使用django betterforms()。这将创建一个用户添加表单,其中包含UserProfile模型中定义的所有字段

    models.py forms.py views.py addUser.html
    这就是我所做的,我认为这是最简单的方法。为新的自定义模型定义对象管理器,然后定义模型

    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
    
    别忘了在
    设置中添加这行代码。py

    AUTH_USER_MODEL = 'YourApp.User'
    
    from django.db import models
    from django.contrib.auth.models import User
    from django.db.models.signals import post_save
    from django.dispatch import receiver
    
    
    class Profile(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        extra_Field_1 = models.CharField(max_length=25, blank=True)
        extra_Field_2 = models.CharField(max_length=25, blank=True)
    
    
    @receiver(post_save, sender=User)
    def create_user_profile(sender, instance, created, **kwargs):
        if created:
            Profile.objects.create(user=instance)
    
    @receiver(post_save, sender=User)
    def save_user_profile(sender, instance, **kwargs):
        instance.profile.save()
    

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

    目前,从Django 2.2开始,启动新项目时推荐的方法是创建一个从AbstractUser继承的自定义用户模型,然后将AUTH_user_模型指向该模型


    资料来源:

    简单有效的方法是 models.py

    from django.contrib.auth.models import User
    class CustomUser(User):
         profile_pic = models.ImageField(upload_to='...')
         other_field = models.CharField()
    

    现在为时已晚,但我的答案是针对那些使用最新版本的Django来寻找解决方案的人

    models.py

    AUTH_USER_MODEL = 'YourApp.User'
    
    from django.db import models
    from django.contrib.auth.models import User
    from django.db.models.signals import post_save
    from django.dispatch import receiver
    
    
    class Profile(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        extra_Field_1 = models.CharField(max_length=25, blank=True)
        extra_Field_2 = models.CharField(max_length=25, blank=True)
    
    
    @receiver(post_save, sender=User)
    def create_user_profile(sender, instance, created, **kwargs):
        if created:
            Profile.objects.create(user=instance)
    
    @receiver(post_save, sender=User)
    def save_user_profile(sender, instance, **kwargs):
        instance.profile.save()
    
    您可以在以下模板中使用它:

    <h2>{{ user.get_full_name }}</h2>
    <ul>
      <li>Username: {{ user.username }}</li>
      <li>Location: {{ user.profile.extra_Field_1 }}</li>
      <li>Birth Date: {{ user.profile.extra_Field_2 }}</li>
    </ul>
    
    def update_profile(request, user_id):
        user = User.objects.get(pk=user_id)
        user.profile.extra_Field_1 = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit...'
        user.save()
    
    试试这个:

    创建名为
    Profile
    的模型,使用
    OneToOneField
    引用用户,并提供
    相关名称的选项

    型号.py

    from django.db import models
    from django.contrib.auth.models import *
    from django.dispatch import receiver
    from django.db.models.signals import post_save
    
    class Profile(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_profile')
    
        def __str__(self):
            return self.user.username
    
    @receiver(post_save, sender=User)
    def create_profile(sender, instance, created, **kwargs):
        try:
            if created:
                Profile.objects.create(user=instance).save()
        except Exception as err:
            print('Error creating user profile!')
    
    from django.http import HttpResponse
    
    def home(request):
        profile = f'profile of {request.user.user_profile}'
        return HttpResponse(profile)
    
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    class CustomUser(AbstractUser):
        extra_field=models.CharField(max_length=40)
    
    现在,要使用
    用户
    对象直接访问配置文件,可以使用
    相关名称

    视图.py

    from django.db import models
    from django.contrib.auth.models import *
    from django.dispatch import receiver
    from django.db.models.signals import post_save
    
    class Profile(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_profile')
    
        def __str__(self):
            return self.user.username
    
    @receiver(post_save, sender=User)
    def create_profile(sender, instance, created, **kwargs):
        try:
            if created:
                Profile.objects.create(user=instance).save()
        except Exception as err:
            print('Error creating user profile!')
    
    from django.http import HttpResponse
    
    def home(request):
        profile = f'profile of {request.user.user_profile}'
        return HttpResponse(profile)
    
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    class CustomUser(AbstractUser):
        extra_field=models.CharField(max_length=40)
    

    在Django版本3.0+中非常简单

    模型中.py

    from django.db import models
    from django.contrib.auth.models import *
    from django.dispatch import receiver
    from django.db.models.signals import post_save
    
    class Profile(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_profile')
    
        def __str__(self):
            return self.user.username
    
    @receiver(post_save, sender=User)
    def create_profile(sender, instance, created, **kwargs):
        try:
            if created:
                Profile.objects.create(user=instance).save()
        except Exception as err:
            print('Error creating user profile!')
    
    from django.http import HttpResponse
    
    def home(request):
        profile = f'profile of {request.user.user_profile}'
        return HttpResponse(profile)
    
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    class CustomUser(AbstractUser):
        extra_field=models.CharField(max_length=40)
    
    设置中.py

    from django.db import models
    from django.contrib.auth.models import *
    from django.dispatch import receiver
    from django.db.models.signals import post_save
    
    class Profile(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_profile')
    
        def __str__(self):
            return self.user.username
    
    @receiver(post_save, sender=User)
    def create_profile(sender, instance, created, **kwargs):
        try:
            if created:
                Profile.objects.create(user=instance).save()
        except Exception as err:
            print('Error creating user profile!')
    
    from django.http import HttpResponse
    
    def home(request):
        profile = f'profile of {request.user.user_profile}'
        return HttpResponse(profile)
    
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    class CustomUser(AbstractUser):
        extra_field=models.CharField(max_length=40)
    
    首先,注册你的新应用,然后在下面验证密码验证程序


    最后,在admin中注册您的模型,运行makemigrations和migrate,它将成功完成。

    我更喜欢Scott的方法,它基于用户对象的继承,而不是直接从模型中删除。有人能说这种方法不明智吗?@BozoJoe-我刚刚在导入转储数据时遇到了这个问题,这似乎是使用这种方法的结果:感谢这个清晰的示例,请注意def create_user。。。。不属于