5.[drf] 유저 어카운트 만들기

유저 어카운트

  • 장고에서 주는 기본 User를 사용하지 않고 직접 설정을 해보도록 하겠습니다.

models.py

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.db import models
from django.utils.translation import gettext_lazy as _
import uuid
from django.utils import timezone
from .managers import CustomUserManager

class User(AbstractBaseUser, PermissionsMixin):
    pkid = models.BigAutoField(primary_key=True, editable=False)
    id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    username = None
    email = models.EmailField(_('email address'), unique=True, db_index=True)
    name = models.CharField(verbose_name=_("first_name"), max_length=50)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    created = models.DateTimeField(default=timezone.now)


    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()

    class Meta:
        verbose_name = (_("user"))
        verbose_name_plural = (_("users"))

    def __str__(self):
        return self.name

managers.py

from django.contrib.auth.base_user import BaseUserManager
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.utils.translation import gettext_lazy as _

class CustomUserManager(BaseUserManager):
    def email_validator(self, email):
        try:
            validate_email(email)
        except ValidationError:
            raise ValidationError(_("You must provide a valid email address"))

    def _create_user(self, email, password, name, **extra_fields):
        """Create a user with the given email and password."""

        if email:
            email = self.normalize_email(email)
            self.email_validator(email)

        else:
            raise ValidationError(_("Admin Account: An email address is required"))

        if not name:
            raise ValueError(_("Users must submit a name"))

        user = self.model(email=email, name=name, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password, name, **extra_fields):
        """Create and save a regular user with the given email and password."""
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, name, **extra_fields)



    def create_superuser(self, email, password, name, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)
        extra_fields.setdefault("is_active", True)

        if extra_fields.get("is_staff") is not True:
            raise ValueError(_("Superusers must have is_staff=True"))

        if extra_fields.get("is_superuser") is not True:
            raise ValueError(_("Superusers must have is_superuser=True"))

        if not password:
            raise ValueError(_("Superusers must have a password"))

        return self._create_user(email, password, name, **extra_fields)

admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.utils.translation import gettext_lazy as _
# from .forms import UserCreationForm, UserChangeForm
from .models import User

class UserAdmin(BaseUserAdmin):
    ordering = ['created']

    model = User
    list_display = [
        "pkid",
        "id",
        "email",
        "name",
        "is_staff",
        "is_active",
    ]
    list_display_links= ["id", "email"]
    list_filter = ["email", "name", "is_staff"]

    fieldsets = (
        (
            _("Login Credentials"), 
            {
                "fields": (
                    "email", 
                    "password",
                )
            },
        ),
        (
            _("Personal Information"),
            {
                "fields": (
                    "name", 
                )
            },
        ),
        (
            _("Permissions and Groups"),
            {
                "fields":(
                    "is_active",
                    "is_staff",
                    "is_superuser"
                )
            }
        ),
        (
            _("Important Dates"),
            {
                "fields":(
                    "last_login",
                    "created",
                )
            }
        )
    )

    add_fieldsets = (
        (
            None,
            {
                "classes": ("wide",),
                "fields": ("email", "password1", "password2", "is_staff", "is_active")
            },
        ),
    )

    search_fields = ["email", "name"]

admin.site.register(User, UserAdmin)

apps.py

from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _

class AccountConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'account'
    verbose_name = _("Account")

좀 더 심플한 버전

models.py

from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db import models
from django.utils.translation import ugettext_lazy as _

class AccountOwnerManager(BaseUserManager):
    """Define a model manager for User model with no username field."""

    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        """Create a user with the given email and password."""
        if not email:
            raise ValueError('Email is required')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        """Create and save a regular user with the given email and password."""
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        """Create and save a super user with the given email and password."""
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        return self._create_user(email, password, **extra_fields)

class AccountOwner(AbstractUser):
    username = None
    email = models.EmailField(_('email address'), unique=True)

    objects = AccountOwnerManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
from django.utils.translation import gettext_lazy as _

from .models import AccountOwner

@admin.register(AccountOwner)
class UserAdmin(DjangoUserAdmin):
    """Define admin model for custom User model with no email field."""

    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        (_('Personal info'), {'fields': ('first_name', 'last_name')}),
        (_('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'),
        }),
    )
    list_display = ('email', 'first_name', 'last_name', 'is_staff')
    search_fields = ('email', 'first_name', 'last_name')
    ordering = ('email',)

serializers.py

from rest_framework import serializers

from .models import AccountOwner

class AccountOwnerSerializer(serializers.ModelSerializer):

    password = serializers.CharField(write_only=True, required=True)

    class Meta:
        model = AccountOwner
        fields = (
            'id', 'email', 'password', 'is_staff',
            'is_active', 'date_joined')

    def create(self, validated_data):
        # TODO do i really need to do this?
        return AccountOwner.objects.create_user(**validated_data)

Did you find this article valuable?

Support Software Engineer at Your Service by becoming a sponsor. Any amount is appreciated!