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


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

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

10 373

10 ответов:

наименее болезненный и действительно Джанго-рекомендуемый способ сделать это с помощью OneToOneField(User) собственность.

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

...

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

что сказал, продлевая django.contrib.auth.models.User и вытеснение его также работает...

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

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

[Ed:два предупреждения и уведомления, отметив, что это довольно резкие.]

Я бы определенно воздержался от изменения фактического класса пользователя в вашем исходном дереве 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'

это создаст userprofile каждый раз, когда пользователь сохраняется, если он создан. Затем вы можете использовать

  user.get_profile().whatever

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

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

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

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

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

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

для людей, которым лень нажимать, вот пример кода (взято из 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

есть официальная рекомендация о хранение дополнительной информации о пользователях. Книга Django также обсуждает эту проблему в разделе профили.

С 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()

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

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

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

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

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

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-код

<!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='addDistributor'),
]

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

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

выдержка:

от Джанго.ВНО.автор.модели импортируют пользователя

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

не забудьте добавить эту строку кода в ваш settings.py:

AUTH_USER_MODEL = 'YourApp.User'

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