๐ django UserModel
Django ์์๋ ํ์ค User Model์ ์ ๊ณตํ๊ณ ์๋ค.
ํด๋น User Model์ django.contrib.auth.models.User์ ๋ค์๊ณผ ๊ฐ์ด ์ ์ ๋์ด ์๋ค.
class User(AbstractUser):
class Meta(AbstractUser.Meta):
swappable = 'AUTH_USER_MODEL'
์๋๋ User ๋ชจ๋ธ์์ ์ ์๋์ด ์๋ ์นผ๋ผ๋ค์ด๋ค.
username = models.CharField()
first_name = models.CharField()
last_name = models.CharField()
email = models.EmailField()
is_staff = models.BooleanField()
is_active = models.BooleanField()
date_joined = models.DateTimeField()
๐ django UserModel ํ์ฅํ๊ธฐ
Django ํ๋ก์ ํธ๋ฅผ ์งํํ๋ค๋ณด๋ฉด, ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ User๋ชจ๋ธ์์ ๋ ํ์ํ ํ๋๊ฐ ์์ ์ ์๋ค. ๋ฐ๋ผ์ User Model์ ํ์ฅํด์ผ ํ๋ ํ์์ฑ์ ๋๋ผ๊ฒ ๋๋๋ฐ, ์ด๋ฅผ ํ์ฅํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์
Django ์์ User Model์ ํ์ฅ ๋๋ ์ปค์คํฐ๋ง์ด์ฆ ํ๋ ๋ฐฉ๋ฒ์ 3๊ฐ์ง๊ฐ ์๋ค.
- ํ์ค User ๋ชจ๋ธ๊ณผ 1๋ 1 ๊ด๊ณ๋ฅผ ๊ฐ์ง๋ ๋ชจ๋ธ์ ๋ง๋๋ ๋ฐฉ๋ฒ
- AbstractUser์ ์์๋ฐ๋ ๋ชจ๋ธ์ ๋ง๋๋ ๋ฐฉ๋ฒ
- AbstractBaseUser์ ์์๋ฐ๋ ๋ชจ๋ธ์ ๋ง๋๋ ๋ฐฉ๋ฒ
๐ ํ์ค User ๋ชจ๋ธ๊ณผ 1๋1 ๊ด๊ณ๋ฅผ ๊ฐ์ง๋ ๋ชจ๋ธ์ ๋ง๋๋ ๋ฐฉ๋ฒ
ํด๋น ๋ฐฉ๋ฒ์ ํ์ค User ๋ชจ๋ธ๊ณผ 1๋1 ๊ด๊ณ๋ฅผ ๊ฐ์ง๋ ๋ชจ๋ธ์ ๋ง๋ค์ด ์ ์ ์ ๋ณด๋ฅผ ์ถ๊ฐํ๊ณ ์ถ์ ์ ๋ณด๋ฅผ ์ด๋ค.
class UserAddInfo(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
department = models.CharField()
image = models.ImageField()
ํ์ง๋ง ํด๋น ๋ฐฉ๋ฒ์ ๊ธฐ์กด ์นผ๋ผ์ ๋ฐ๋์ ์ด์ฉํ์ฌ์ผ ํ๋ฉฐ, email๋ก ๋ก๊ทธ์ธํ ์ ์ ๋๋ก ๋ณ๊ฒฝํ ์ ์๋ค. ๋ํ ํ ์ด๋ธ์ด ์ฌ๋ฌ๊ฐ๋ก ๋๋๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ๋ฉด ์์๋ ๋ดค์๋๋ ์ข์ง ์๊ธฐ์, ํฌ๊ฒ ์ถ์ฒํ์ง ์๋ ๋ฐฉ์์ด๋ค.
๐ AbstarctUser์ ์์ํ ๋ชจ๋ธ์ ๋ง๋๋ ๋ฐฉ๋ฒ
AbstaractUser์ ํ์ค User ๋ชจ๋ธ์ด ์์ํ์ฌ ์ด์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค. AbstractUser ๋ชจ๋ธ์ django.contrib.auth.models์ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋์ด ์๋ค.
class AbstractUser(AbstractBaseUser, PermissionsMixin):
# ๊ธฐ๋ณธ ์ ๊ณต ์์ฑ
username_validator = UnicodeUsernameValidator()
username = models.CharField(_('username'), max_length=150, unique=True,…)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True)
email = models.EmailField(_('email address'), blank=True)
is_staff = models.BooleanField(_('staff status'), default=False,…)
is_active = models.BooleanField(_('active'), default=True,…)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = UserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
abstract = True
AbstaractUser์ AbstaractUser๊ณผ PermissionMixin์ ์์๋ฐ๊ณ ์๋ค. ํด๋น ๋ฐฉ๋ฒ์ ํ ์ด๋ธ์ด ์ฌ๋ฌ ๊ฐ๋ก ๋๋์ด ํผํฌ๋จผ์ค๊ฐ ๋๋น ์ง๋ ๋ฑ์ ๋ถํธํจ์ ์์ง๋ง, ์นผ๋ผ(์์ฑ) ์ถ๊ฐ๋ง ๊ฐ๋ฅํ๋ฏ๋ก ๋ชจ๋ธ์ ์ ์ฐ์ฑ์ด ๋ฎ๋ค.
ํ์ค User ๋ชจ๋ธ์ ์นผ๋ผ๋ง์ ์ถ๊ฐํ๊ณ ์ถ์ ๊ฒฝ์ฐ์๋ ์ด ๋ฐฉ๋ฒ์ ์ด์ฉํ๋ฉด ํธ๋ฆฌํ๋ค.
๐ AbstarctUser์ ์์ํ ๋ชจ๋ธ์ ๋ง๋๋ ๋ฐฉ๋ฒ
AbstractBaseUser์ django.contrib.auth.base_user์ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋์ด ์๋ค.
class AbstractBaseUser(models.Model):
password = models.CharField(_('password'), max_length=128)
last_login = models.DateTimeField(_('last login'), blank=True, null=True)
is_active = True
REQUIRED_FIELDS = []
_password = None
class Meta:
abstract = True
AbstractBaseUser์ django.db.models.Model ์์ ๋ฐ๊ณ ์๋ค. AbstractBaseUser์๋ ์ธ์ฆ ๊ธฐ๋ฅ์ด ํฌํจ๋์ด ์์ผ๋ฏ๋ก ๋ ์์ ์ธ ํ๋๋ฅผ ์ค์ ํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค.
์ฆ, ์ธ์ฆ ์ด์ธ์ ๋ถ๋ถ์ ์ด๋ค ๊ฒ๋ ๊ตฌํ๋์ด ์์ง์์ ํด๋์ค๋ก, first_name์ด๋ last_name์ด๋ผ๋ ํ์์๋ ํ๋๋ฅผ User ๋ชจ๋ธ์ ์ฐ์ง ์์๋๋๋ค. AbstractBaseUser์ ์์๋ฐ๋ User ๋ชจ๋ธ์ ๋ง๋๋ ๊ฒ์ ๊ท์ฐฎ์ง๋ง, ์ปค์คํฐ๋ง์ด์ฆ์ ์ ์ฐ์ฑ์ด ๋ฐฉ๋ฒ ์ค์ด ๊ฐ์ฅ ๋๋ค.
ํด๋น ์ปค์คํ User ๋ชจ๋ธ์ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
from django.db import models
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.core.mail import send_mail
from django.utils import timezone
from django.contrib.auth.validators import UnicodeUsernameValidator
from django.utils.translation import gettext_lazy as _
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, username, email, password, **extra_fields):
if not email:
raise ValueError('Email์ ์
๋ ฅํด์ฃผ์ธ์.')
email = self.normalize_email(email)
username = self.model.normalize_username(username)
user = self.model(username=username, email=email, **extra_fields)
user.set_password(password)
user.save(using=self.db)
return user
def create_user(self, username, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, username, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('is_staff=True์ผ ํ์๊ฐ ์์ต๋๋ค.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('is_superuser=True์ผ ํ์๊ฐ ์์ต๋๋ค.')
return self._create_user(username, email, password, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
username_validator = UnicodeUsernameValidator()
username = models.CharField(_("username"), max_length=50, validators=[username_validator], blank=True)
email = models.EmailField(_("email_address"), unique=True)
is_staff = models.BooleanField(_("staff status"), default=False)
is_active = models.BooleanField(_("active"), default=True)
date_joined = models.DateTimeField(_("date joined"), default=timezone.now)
objects = UserManager()
USERNAME_FIELD = "email"
EMAIL_FIELD = "email"
REQUIRED_FIELDS = ['username']
class Meta:
verbose_name = _("user")
verbose_name_plural = _("users")
def clean(self):
super().clean()
self.email = self.__class__.objects.normalize_email(self.email)
def email_user(self, subject, message, from_email=None, **kwargs):
send_mail(subject, message, from_email, [self.email], **kwargs)
- UserManager
ํฐ๋ฏธ๋์์ ์ ์ ๋ฅผ ์์ฑํ ๋ ํธ์ถ๋๋ ํด๋์ค์ด๋ค.
- User
- object : ํด๋น ๋ชจ๋ธ์์ objects ๋ณ์๋ views.py ์์ User ๋ชจ๋ธ์ ์ ๋ณด๋ฅผ ์ป์ ๋ ์ด์ฉํ๋ค.
user = User.objects.get(username="blank")
- USERNAME_FIELD :๊ณ ์ ์๋ณ์๋ก ์ฌ์ฉ๋๋ ์ฌ์ฉ์ ๋ชจ๋ธ์ ํ๋ ์ด๋ฆ์ ์ค๋ช
ํ๋ ๋ฌธ์์ด์ด๋ค. ์ด๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ์ผ์ข
์ ์ฌ์ฉ์ ์ด๋ฆ์ด์ง๋ง ์ด๋ฉ์ผ ์ฃผ์ ๋๋ ๊ธฐํ ๊ณ ์ ์๋ณ์์ผ ์๋ ์๋ค.
- EMAIL_FIELD : ๋ชจ๋ธ์ ์ด๋ฉ์ผ ํ๋ ์ด๋ฆ์ ์ค๋ช
ํ๋ ๋ฌธ์์ด์ด๋ค. User ๊ฐ์ get_email_field_name()์ ์ํด ๋ฐํ๋ฉ๋๋ค
- is_active : ์ฌ์ฉ์๊ฐ "ํ์ฑ"์ผ๋ก ๊ฐ์ฃผ๋๋์ง ์ฌ๋ถ๋ฅผ ๋ํ๋ด๋ Bool ์์ฑ
- is_staff : ์คํํ ๊ถํ
- clean() : normalize_username()์ ํธ์ถํ์ฌ ์ฌ์ฉ์ ์ด๋ฆ์ ์ ๊ทํ ํ๋ค. super()์ด ๋งค์๋๋ฅผ ์ฌ์ ์ํ ๋๋ ์ ๊ทํ๋ฅผ ์ ์งํ๊ธฐ ์ํด ํธ์ถํ์ฌ์ผ ํ๋ค.
๐ settings.py
AUTH_USER_MODEL = 'users.User'
๐ admin.py
๊ด๋ฆฌ์ ์ฌ์ดํธ์ ์ปค์คํ User์ ์ด์ฉํ ์ ์๋๋ก ํ๊ธฐ ์ํด ์ดํ๋ฆฌ์ผ์ด์ ์ admin.py์ ๋ณ๊ฒฝํ๋ค. ๋ํ ์ด ์ฝ๋์์๋ UserCreationForm ์ด๋ UserCahngeForm๋ ๊ทธ๋๋ก ์ด์ฉํ ์ ์์ผ๋ฏ๋ก ์ ์ฉ Form์ ๋ง๋ค์๋ค.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from django.utils.translation import gettext_lazy as _
from .models import User
class MyUserChangeForm(UserChangeForm):
class Meta:
model = User
fields = '__all__'
class MyUserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ('email','username')
class MyUserAdmin(UserAdmin):
fieldsets = (
(None, {'fields': ('email', 'password', 'username')}),
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2'),
}),
)
form = MyUserChangeForm
add_form = MyUserCreationForm
list_display = ('email', 'username', 'is_staff')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
search_fields = ('email', 'username')
ordering = ('email',)
admin.site.register(User, MyUserAdmin)
์ฐธ์กฐ :
https://engineer-mole.tistory.com/301
[Django] User๋ชจ๋ธ ์ปค์คํฐ๋ง์ด์ฆํ๊ธฐ (์ปค์คํ User ๋ชจ๋ธ)
โป์ผ๋ณธ์ ํ ๋ธ๋ก๊ทธ ๊ธ์ ๋ฒ์ญํ ํฌ์คํธ์ ๋๋ค. ์์ญ ๋ฐ ์ง์ญ, ์ค์ญ์ด ์์ ์ ์์ผ๋ฉฐ ํ๋ฆฐ ๋ด์ฉ์ ์ง์ ํด์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค. Django์์๋ ํ์ค User ๋ชจ๋ธ์ด ์ ์๋์ด ์๋ค. ๊ทธ๋ฌ๋ ๋๋ถ๋ถ์
engineer-mole.tistory.com
04) ์ปค์คํ User ๋ชจ๋ธ (AbstractBaseUser์ ์์)
[TOC] # AbstractBaseUser ํด๋์ค ์์์ ์ฅ๋จ์ ```AbstractBaseUser``` ๋ชจ๋ธ์ ์์ํ User ์ปค์คํ ๋ชจ๋ธ์ ๋ง๋ค๋ฉด ๋ก๊ทธ์ธ ์์ด๋๋ก ์ด๋ฉ์ผ …
wikidocs.net