[django] Django에서 사용자 정의 필드로 사용자 모델 확장

사용자 정의 필드로 사용자 모델 (Django의 인증 앱과 함께 제공)을 확장하는 가장 좋은 방법은 무엇입니까? 이메일을 사용자 이름으로 사용하고 싶습니다 (인증 목적으로).

나는 이미 가지 방법 을 보았지만 어느 것이 가장 좋은 지 결정할 수 없습니다.



답변

가장 고통스럽고 실제로 장고가 권장하는 방법은 OneToOneField(User)속성을 통하는 것 입니다.

기존 사용자 모델 확장

와 관련된 정보를 저장하려는 경우 추가 정보를위한 필드가 포함 된 모델에 일대일 관계User사용할 수 있습니다 . 이 일대일 모델을 사이트 모델에 대한 인증되지 않은 관련 정보를 저장할 수 있으므로 종종 프로필 모델이라고합니다.

즉, django.contrib.auth.models.User그것을 확장 하고 대체하는 것도 효과가 있습니다 …

사용자 정의 사용자 모델 대체

일부 종류의 프로젝트에는 Django의 내장 User모델이 항상 적합하지 않은 인증 요구 사항이있을 수 있습니다 . 예를 들어, 일부 사이트에서는 사용자 이름 대신 전자 메일 주소를 식별 토큰으로 사용하는 것이 더 합리적입니다.

[Ed : 두 가지 경고와 알림 이 이어지는데, 이는 상당히 과감한 것 입니다.]

Django 소스 트리에서 실제 사용자 클래스를 변경하거나 인증 모듈을 복사 및 변경하지 마십시오.


답변

참고 :이 답변은 더 이상 사용되지 않습니다. 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_MODULE1.5 버전부터 사용되지 않습니다 : https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module


답변

글쎄요, 2008 년 이후 어느 정도 시간이 지났고 이제는 새로운 답변을 얻을 시간입니다. Django 1.5부터 사용자 정의 사용자 클래스를 만들 수 있습니다. 실제로, 나는 이것을 쓸 때 이미 마스터로 병합되어 있으므로 시도해 볼 수 있습니다.

그것에 대한 몇 가지 정보가 있습니다 이 커밋 문서 있거나 더 깊이 파고 싶다면 여기에 커밋하십시오 .

당신이해야 할 추가 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 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()


답변

사용자에 대한 추가 정보 저장 에 대한 공식 권장 사항이 있습니다 . Django Book은이 문제에 대해서도 프로파일 섹션에서 설명합니다 .


답변

아래는 사용자를 확장하는 또 다른 방법입니다. 두 가지 접근 방식보다 더 명확하고 쉽고 읽기 쉽다고 생각합니다.

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

    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)

새 사용자가 생성되면 직원 인스턴스가 자동으로 생성됩니다.

사용자 모델을 확장하고 사용자를 작성하는 동안 추가 정보를 추가하려는 경우 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):

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