Modeling & Serializing


Djangoについて簡単に紹介し、プロジェクトやアプリケーションを始めた以上、MVTのM.Modelingを始めましょう.

Modeling


モデリングとは、データストレージのフォーマットを決定することです.この文書では、プロジェクトに必要な複数のアプリケーションで、ユーザーセクションのみを表示します.
Djangoはユーザーに強力なユーザーモデルを提供しています.
# user/models.py
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
from django.contrib.auth.models import UserManager, AbstractBaseUser, PermissionsMixin, BaseUserManager

GENDER_CHOICES = (("M", "남성"), ("W", "여성"))
IS_MARRIED = (("T", "기혼"), ("F", "미혼"))

# Create your models here
class UserManager(BaseUserManager):
    def create_user(self, email, username, name, password, **extra_fields):
        if not email:
            raise ValueError(('The Email must be set'))
        email = self.normalize_email(email)
        user = self.model(email=email, username = username, name = name, **extra_fields)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email, username, name, password, **extra_fields):
        """
        Create and save a SuperUser with the given email and password.
        """
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', False)
        extra_fields.setdefault('is_active', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError(('Superuser must have is_staff=True.'))
        if extra_fields.get('is_superuser') is not True:
            raise ValueError(('Superuser must have is_superuser=True.'))
        user = self.create_user(email, password, username, name, **extra_fields)
        user.is_admin = True
        user.save(using=self._db)
        return user




class User(AbstractBaseUser, PermissionsMixin):
    objects = UserManager()

    name = models.CharField(verbose_name="이름", max_length=10)
    username = models.CharField(verbose_name="ID", max_length=20, unique=True)
    email = models.CharField(verbose_name="이메일", max_length=30, blank=True)
    gender = models.CharField(
        verbose_name="성별",
        max_length=10,
        choices=GENDER_CHOICES,
        blank=True,
        default="남성",
    )
    staff_number = models.IntegerField(verbose_name="사원번호", blank=True, null=True)
    level = models.IntegerField(
        verbose_name="접근 레벨",
        default=0,
        validators=[MinValueValidator(0), MaxValueValidator(5)],
        blank=True,
    )
    department = models.ForeignKey(
        "Department", on_delete=models.SET_NULL, blank=True, null=True
    )
    team = models.ForeignKey("Team", on_delete=models.SET_NULL, blank=True, null=True)
    phone_number = models.CharField(verbose_name="전화번호", max_length=12, blank=True)
    address = models.CharField(verbose_name="주소", max_length=50, blank=True)
    account = models.CharField(verbose_name="계좌번호", max_length=30, blank=True)
    date_of_birth = models.DateField(
        verbose_name="생년월일", blank=True, default="1900-01-01"
    )
    date_of_employment = models.DateField(
        verbose_name="입사일", blank=True, default="1900-01-01"
    )
    is_married = models.CharField(
        verbose_name="결혼 여부",
        max_length=5,
        choices=IS_MARRIED,
        blank=True,
        default=False,
    )
    created_at = models.DateTimeField(auto_now_add=True)

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['name','email',]

    class Meta:
        ordering = ("level",)
必要なプレイヤーフィールドに基づいて作成されます.Eメール、ニックネーム、名前、パスワードは、初めて会員に加入するときに必要な基本情報であり、パスワードはデータベースに格納されるときに基本的に暗号化されて格納されます.
その他のフィールドは次のとおりです.CharField:文字列フィールド(max lengthは必須)DateField:日付フィールドIntegerField:整数フィールドForeignKey:外部キー(他のテーブルに関連付けられている)

Serializing


しかし、このモデルがそのまま使えるわけではありません.フロントと通信しjsonオブジェクト形式でデータを交換するため,シーケンス化が必要である.したがって、アプリケーションにシーケンス化器を追加します.pyという名前のファイルを生成します.
# user/serializers.py
from rest_framework import fields, serializers
from .models import *
from django.contrib.auth import get_user_model
from django.contrib.auth.models import update_last_login
from django.contrib.auth import authenticate
from rest_framework_jwt.settings import api_settings

User = get_user_model()

# JWT 사용을 위한 설정
JWT_PAYLOAD_HANDLER = api_settings.JWT_PAYLOAD_HANDLER
JWT_ENCODE_HANDLER = api_settings.JWT_ENCODE_HANDLER
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = "__all__"

    def create(self, validated_data):
        return super().create(validated_data)

    def update(self, instance, validated_data):
        return super().update(instance, validated_data)


class UserCreateSerializer(serializers.Serializer):
    email = serializers.EmailField(required=True)
    username = serializers.CharField(required=True)
    password = serializers.CharField(required=True)
    name = serializers.CharField(required=True)
    phone_number = serializers.CharField(required=True)
    def create(self, validated_data):
        user = User.objects.create( # User 생성
            email=validated_data['email'],
            username=validated_data['username'],
            name = validated_data['name'],
            phone_number = validated_data['phone_number']
        )
        user.set_password(validated_data['password'])

        user.save()
        return user
        
  class UserLoginSerializer(serializers.Serializer):
    username = serializers.CharField(max_length=30)
    password = serializers.CharField(max_length=128, write_only=True)
    token = serializers.CharField(max_length=255, read_only=True)

    def validate(self, data):
        username = data.get("username")
        password = data.get("password", None)
        # 사용자 아이디와 비밀번호로 로그인 구현(<-> 사용자 아이디 대신 이메일로도 가능)
        user = authenticate(username=username, password=password)
        print("SERIALIZE USER : ",user)
        if user is None:
            return {'id': 'None','username':username}
        try:
            payload = JWT_PAYLOAD_HANDLER(user) # payload 생성
            jwt_token = JWT_ENCODE_HANDLER(payload) # jwt token 생성
            update_last_login(None, user)

        except User.DoesNotExist:
            raise serializers.ValidationError(
                'User with given username and password does not exist'
            )
        return {
            'id':user.id,
            'token': jwt_token
        }

class UserIdSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id',)
このファイルには、フロントと通信および交換するデータ・フォームも含まれます.特にLogin機能には、Djangoでユーザモデルを使用する最大の理由(少なくとも私にとって)として、本プロジェクトで使用するjwtトークン認証機能が含まれています.
次の記事では、ViewsとUrlsを終了し、フロントとの通信を終了します.