Расширение модели пользователя с помощью настраиваемых полей в Django

Каков наилучший способ расширить модель User (в комплекте с приложением для проверки подлинности Django) с помощью настраиваемых полей? Я также хотел бы использовать электронное письмо в качестве имени пользователя (для целей аутентификации).

Я уже видел несколько способов сделать это, но не могу решить, какой из них лучше.

    Наименее болезненный и действительно рекомендованный Django способ сделать это – это OneToOneField(User) .

    Расширение существующей модели пользователя

    Если вы хотите хранить информацию, связанную с User , вы можете использовать взаимно-однозначное отношение к модели, содержащей поля для получения дополнительной информации. Эта модель «один-к-одному» часто называется моделью профиля, поскольку она может хранить информацию, не связанную с auth, о пользователе сайта.

    Тем не менее, расширяя django.contrib.auth.models.User и вытесняя его, он также работает …

    Подстановка пользовательской модели пользователя

    Некоторые проекты могут иметь требования к аутентификации, для которых встроенная User модель Django не всегда подходит. Например, на некоторых сайтах имеет смысл использовать адрес электронной почты в качестве идентификационного токена вместо имени пользователя.

    [Ред. Два предупреждения и уведомление следуют , отметив, что это довольно решительно .]

    Я бы определенно держался подальше от изменения фактического classа User в вашем исходном дереве Django и / или копировании и изменении модуля auth.

    Примечание: этот ответ устарел. см. другие ответы, если вы используете 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 

    Вот еще информация из документов

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

    Обновление: обратите внимание, что AUTH_PROFILE_MODULE устарел с AUTH_PROFILE_MODULE v1.5: https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module

    Ну, какое-то время прошло с 2008 года, и пришло время для нового ответа. С Django 1.5 вы сможете создать пользовательский class. Фактически, в то время, когда я пишу это, оно уже слилось с мастером, поэтому вы можете попробовать его.

    В документации есть некоторая информация об этом, или если вы хотите углубиться в нее, в этой фиксации .

    Все, что вам нужно сделать, – добавить AUTH_USER_MODEL к настройкам с помощью пути к пользовательскому classу пользователя, который расширяет либо AbstractBaseUser (более настраиваемая версия), либо AbstractUser (более или менее старый class пользователя, который вы можете расширить).

    Для людей, которые ленивы щелкнуть, вот пример кода (взятый из документов ):

     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 с 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 с 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, вы можете легко расширить модель пользователя и сохранить отдельную таблицу в базе данных.

     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")) 

    Вы также должны настроить его как текущий пользовательский class в файле настроек

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

    Если вы хотите добавить много предпочтений пользователей, опция OneToOneField может быть лучшим выбором.

    Примечание для людей, разрабатывающих библиотеки сторонних разработчиков: если вам нужно получить доступ к пользовательскому classу, помните, что люди могут его изменить. Используйте официальный помощник, чтобы получить нужный class

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

    Ниже приведен другой подход к расширению пользователя. Я чувствую, что это более ясно, легко, читаемо, а затем выше двух подходов.

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

    Использование вышеуказанного подхода:

    1. вам не нужно использовать user.get_profile (). newattribute для доступа к дополнительной информации, связанной с пользователем
    2. вы можете просто получить доступ к дополнительным новым атрибутам через user.newattribute

    Вы можете просто расширить профиль пользователя, создав новую запись каждый раз, когда пользователь создается с помощью django post save сигналов

    models.py

     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 ). Это создаст форму добавления пользователя со всеми полями, определенными в модели userProfile.

    models.py

     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) 

    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 = ('userName',) 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 = "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) 

    addUser.html

         Title   
    {% csrf_token %} {{ form }}

    urls.py

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

    Расширение пользовательской модели Django (UserProfile), например, Pro

    Я нашел это очень полезным: ссылка

    Экстракт:

    from django.contrib.auth.models import Пользователь

     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 1.5, теперь вы можете создать свою собственную пользовательскую модель пользователя (что, похоже, хорошо в этом случае). См. «Настройка аутентификации в Django»

    Наверное, самая крутая новая функция в версии 1.5.

    Это то, что я делаю, и это, на мой взгляд, самый простой способ сделать это. определите диспетчер объектов для вашей новой настраиваемой модели, а затем определите свою модель.

     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 с 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 :

     AUTH_USER_MODEL = 'YourApp.User' 

    Это то, что я делаю, и оно всегда работает.

    Давайте будем гением компьютера.