Extending the User model with custom fields in Django

后端 未结 13 1427
别那么骄傲
别那么骄傲 2020-11-21 23:28

What\'s the best way to extend the User model (bundled with Django\'s authentication app) with custom fields? I would also possibly like to use the email as the username (fo

相关标签:
13条回答
  • 2020-11-22 00:14

    This is what i do and it's in my opinion simplest way to do this. define an object manager for your new customized model then define your model.

    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
    

    Dont forget to add this line of code in your settings.py:

    AUTH_USER_MODEL = 'YourApp.User'
    

    This is what i do and it always works.

    0 讨论(0)
  • 2020-11-22 00:18

    Currently as of Django 2.2, the recommended way when starting a new project is to create a custom user model that inherits from AbstractUser, then point AUTH_USER_MODEL to the model.

    Source: https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project

    0 讨论(0)
  • 2020-11-22 00:19

    There is an official recommendation on storing additional information about users. The Django Book also discusses this problem in section Profiles.

    0 讨论(0)
  • 2020-11-22 00:19

    You can Simply extend user profile by creating a new entry each time when a user is created by using Django post save signals

    models.py

    from django.db.models.signals import *
    from __future__ import unicode_literals
    
    class UserProfile(models.Model):
    
        user_name = models.OneToOneField(User, related_name='profile')
        city = models.CharField(max_length=100, null=True)
    
        def __unicode__(self):  # __str__
            return unicode(self.user_name)
    
    def create_user_profile(sender, instance, created, **kwargs):
        if created:
            userProfile.objects.create(user_name=instance)
    
    post_save.connect(create_user_profile, sender=User)
    

    This will automatically create an employee instance when a new user is created.

    If you wish to extend user model and want to add further information while creating a user you can use django-betterforms (http://django-betterforms.readthedocs.io/en/latest/multiform.html). This will create a user add form with all fields defined in the UserProfile model.

    models.py

    from django.db.models.signals import *
    from __future__ import unicode_literals
    
    class UserProfile(models.Model):
    
        user_name = models.OneToOneField(User)
        city = models.CharField(max_length=100)
    
        def __unicode__(self):  # __str__
            return unicode(self.user_name)
    

    forms.py

    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 = ('user_name',)
    
    
    class addUserMultiForm(MultiModelForm):
        form_classes = {
            'user':UserCreationForm,
            'profile':ProfileForm,
        }
    

    views.py

    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 = "add-user.html"
        success_url = '/your-url-after-user-created'
    
        def form_valid(self, form):
            user = form['user'].save()
            profile = form['profile'].save(commit=False)
            profile.user_name = User.objects.get(username= user.username)
            profile.save()
            return redirect(self.success_url)
    

    addUser.html

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>Title</title>
        </head>
        <body>
            <form action="." method="post">
                {% csrf_token %}
                {{ form }}     
                <button type="submit">Add</button>
            </form>
         </body>
    </html>
    

    urls.py

    from django.conf.urls import url, include
    from appName.views import *
    urlpatterns = [
        url(r'^add-user/$', AddUser.as_view(), name='add-user'),
    ]
    
    0 讨论(0)
  • 2020-11-22 00:22

    Note: this answer is deprecated. see other answers if you are using Django 1.7 or later.

    This is how I do it.

    #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'
    

    This will create a userprofile each time a user is saved if it is created. You can then use

      user.get_profile().whatever
    

    Here is some more info from the docs

    http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users

    Update: Please note that AUTH_PROFILE_MODULE is deprecated since v1.5: https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module

    0 讨论(0)
  • 2020-11-22 00:25

    Well, some time passed since 2008 and it's time for some fresh answer. Since Django 1.5 you will be able to create custom User class. Actually, at the time I'm writing this, it's already merged into master, so you can try it out.

    There's some information about it in docs or if you want to dig deeper into it, in this commit.

    All you have to do is add AUTH_USER_MODEL to settings with path to custom user class, which extends either AbstractBaseUser (more customizable version) or AbstractUser (more or less old User class you can extend).

    For people that are lazy to click, here's code example (taken from docs):

    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
    
    0 讨论(0)
提交回复
热议问题