Django Customユーザー


DjangoのAbstractBaseUserをカスタマイズして独自のモデルを作成
  • accounts/models.py
  • from django.db import models
    from django.contrib.auth.models import (
        AbstractBaseUser,
        BaseUserManager,
    )
    
    # Create your models here.
    class UserManager(BaseUserManager):
        def create_user(self, username, email, **extra_fields):
            try:
                user = self.model(
                    email=self.normalize_email(email), username=username, **extra_fields
                )
                return user
            except Exception as e:
                print("CREATE USER ERROR : ", e)
    
        def create_superuser(self, username, email=None, password=None, **extra_fields):
            superuser = self.create_user(
                username=username, email=self.normalize_email(email)
            )
    
            superuser.is_superuser = True
            superuser.is_admin = True
            superuser.is_active = True
            superuser.is_staff = True
    
            superuser.set_password(password)
            superuser.save(using=self.db)
            return superuser
    
    
    class User(AbstractBaseUser):
        objects = UserManager()
    
        GENDER_MALE = "Male"
        GENDER_FEMALE = "Female"
    
        GENDER_CHOICES = ((GENDER_MALE, "Male"), (GENDER_FEMALE, "Female"))
    
        username = models.CharField(max_length=20, unique=True)
        email = models.EmailField(max_length=100)
        gender = models.CharField(choices=GENDER_CHOICES, blank=True, max_length=10)
        is_staff = models.BooleanField(default=False)
        is_admin = models.BooleanField(default=False)
        is_superuser = models.BooleanField(default=False)
        is_active = models.BooleanField(default=True)
        created_at = models.DateTimeField(auto_now_add=True)
    
        USERNAME_FIELD = "username"
    
        def __str__(self):
            return self.email
    
        def has_module_perms(self, app_label):
            # return self.is_admin
            return True
    
        def has_perm(self, perm, obj=None):
            # return self.is_admin
            return True
  • accounts/forms.py
  • from django import forms
    from django.contrib.auth.forms import ReadOnlyPasswordHashField
    from django.utils.translation import ugettext_lazy as _
    from . import models as user_models
    
    
    class UserCreationForm(forms.ModelForm):
        # 사용자 생성 폼
        email = forms.EmailField(
            label=_("Email"),
            required=True,
            widget=forms.EmailInput(
                attrs={
                    "class": "form-control",
                    "placeholder": _("Email address"),
                    "required": "True",
                }
            ),
        )
        username = forms.CharField(
            label=_("Username"),
            required=True,
            widget=forms.TextInput(
                attrs={
                    "class": "form-control",
                    "placeholder": _("Username"),
                    "required": "True",
                }
            ),
        )
        password1 = forms.CharField(label="Password", widget=forms.PasswordInput)
        password2 = forms.CharField(
            label="Password confirmation", widget=forms.PasswordInput
        )
    
        class Meta:
            model = user_models.User
            fields = (
                "email",
                "username",
            )
    
        def clean_password2(self):
            # 두 비밀번호 입력 일치 확인
            password1 = self.cleaned_data.get("password1")
            password2 = self.cleaned_data.get("password2")
            if password1 and password2 and password1 != password2:
                raise forms.ValidationError("Passwords don't match")
            return password2
    
        def save(self, commit=True):
            # Save the provided password in hashed format
            user = super(UserCreationForm, self).save(commit=False)
            user.email = user_models.UserManager.normalize_email(self.cleaned_data["email"])
            user.set_password(self.cleaned_data["password1"])
            if commit:
                user.save()
            return user
    
    
    class UserChangeForm(forms.ModelForm):
        # 비밀번호 변경 폼
        password = ReadOnlyPasswordHashField(label=_("Password"))
    
        class Meta:
            model = user_models.User
            fields = ("email", "password", "is_active", "is_superuser")
    
        def clean_password(self):
            # Regardless of what the user provides, return the initial value.
            # This is done here, rather than on the field, because the
            # field does not have access to the initial value
            return self.initial["password"]
    
  • accounts/admin.py
  • from django.contrib import admin
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    from . import forms
    from . import models as user_models
    
    # Register your models here.
    @admin.register(user_models.User)
    class CustomUserAdmin(BaseUserAdmin):
        form = forms.UserChangeForm
        add_form = forms.UserCreationForm
    
        list_display = (
            "pk",
            "email",
            "username",
        )
        list_filter = ("is_admin",)
    
        fieldsets = (
            (
                None,
                {
                    "fields": (
                        "email",
                        "password",
                    ),
                },
            ),
            ("Permissions", {"fields": ("is_admin",)}),
        )
        add_fieldsets = (
            (
                None,
                {
                    "classes": ("wide",),
                    "fields": ("email", "username", "password1", "password2"),
                },
            ),
        )
    
        filter_horizontal = ()
    
  • accounts/views.py
  • from django.shortcuts import render
    from rest_framework.views import APIView
    from rest_framework import status
    from rest_framework.response import Response
    from . import serializers
    
    # Create your views here.
    
    
    class SignupView(APIView):
        def post(self, request, format=None):
            serializer = serializers.SignupSerializer(data=request.data)
    
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_200_OK)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  • accounts/serializers.py
  • from rest_framework import serializers
    from . import models as user_models
    
    
    class SignupSerializer(serializers.ModelSerializer):
        password = serializers.CharField(write_only=True)
    
        def create(self, validated_data):
            if validated_data["email"]:
                req_password = validated_data.pop("password")
                user = user_models.User.objects.create_user(**validated_data)
                user.set_password(req_password)
                user.save()
                print("CREATED USER : ", user)
                return user
    
        class Meta:
            model = user_models.User
            fields = "__all__"
    これは最も基本的なAbstractBaseUserを継承します.
    完全にカスタマイズできます.
    これからはプレイヤーモデルがこのようにしたほうがいいと思います.