[DRF Project]掲示板#2の作成


仮想環境の設定


筆者はanaconda環境で開発を行い,コードがやや異なる可能性がある.以下に、基本的なプリファレンスパラメータに使用するコードを示します.
# 가상환경 생성
conda create --name=drf_forum python='3.9'

# 가상환경 활성화
conda activate drf_forum

# 가상환경내 mysqlclient 설치
pip install mysqlclient

# 가상환경내 Django REST Framework 설치
pip install djangorestframework

データベースの作成


mysqlを使用してデータベースを作成します.mysql shellでデータベースを作成するためのコードを以下に示します.

# mysql shell 열기
mysql -u root -p

# mysql shell에서 database 생성
> CREATE DATABASE drf_forum CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci
あとはDjangoモデルpy内で作成したコンテンツに基づいて移行し、本プロジェクトのデータベースを作成します.

DRFディレクトリの構成


筆者がDRFを使用する際に困ったことは、「ディレクトリをどのようにRESTfulで整理するか」です.はい.DRFでは、誰もが異なるフォルダ構成を使用できます.△筆者の考え.したがって、次の例は正解ではなく、参考にするだけで役に立つかもしれません.
最初にしなければならないのはDjango appをインストールすることです.プロジェクトに必要なDjango appは、user(ユーザー)、post(投稿)の2つで、次のコードを使用してappをインストールします.
# user app 설치
django-admin startapp user

# post app 설치
django-admin startapp post
インストール後に表示されるディレクトリ構造は次のとおりです.

ただし、次の構造を使用してディレクトリを変更します.ursl.py, views.pyの場合、親ディレクトリのpost、ユーザフォルダ内のファイルには書き込まず、apiフォルダのpost、ユーザフォルダ内のファイルに書き込むのが特徴です.

DRFプリファレンスの設定


Djangoのデフォルト設定はmy settingsです.py,drf forum/settingsを作成します.py設定などの項目を行うには、以下の操作(?)を行います.簡単な仕事をしなければならない.設定されたファイルディレクトリと設定事項は、おおむね次のようになります.
/drf_forum/settings.py
/my_settings.py

# 1. 주석제거하기
# 2. SECRET_KEY 내용 my_settings.py 옮기기
# 3. DATABASES 내용 my_settings.py 옮기기
# 4. 기타사항 (ALLOWED_HOST 세팅, ALGRORITHM 설정 , 설치된 앱 추가하기 등)

User appの設定


DRFでユーザ関連アプリを設定する方法はいろいろあります.このプロジェクトでは、JWTトークン検証/view:genericsview/serializer:model serializerを使用して設定します.
  • models.pyの設定
    BaseUserManagerを使用して、本プロジェクトの状況に合わせてcreate user、create staff、create superuserの方法を変更しました.
  • /user/models.py
    from django.db                  import models
    from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
    
    class UserManager(BaseUserManager):
        
        def create_user(self, email, nickname, password):
            
            if not email:    
                raise ValueError('must have user email')
            
            if not nickname:    
                raise ValueError('must have user nickname')
    
            user = self.model(
                    email       = self.normalize_email(email),
                    nickname    = nickname
                    )
            user.set_password(password)
            user.save(using=self._db)
            return user
    
        def create_staff(self, email, nickname, password):
            user = self.create_user(
                    email,
                    nickname = nickname,
                    password = password
                    )
            user.is_staff = True
            user.save(using=self._db)
            return user
    
        def create_superuser(self, email, nickname, password):
            user = self.create_user(
                    email,
                    nickname = nickname,
                    password = password
                    )
            user.is_superuser = True
            user.save(using=self._db)
            return user
    
    class User(AbstractBaseUser):
        
        email = models.CharField(
                verbose_name    = 'email',
                max_length      = 100,
                unique          = True
                )
    
        nickname = models.CharField(
                verbose_name    = 'nickname',
                max_length      = 10,
                unique          = True
                )
    
        is_active = models.BooleanField(
                verbose_name    = 'is_active',
                default         = True 
                )
    
        is_staff = models.BooleanField(
                verbose_name    = 'is_staff',
                default         = False
                )
    
        is_superuser = models.BooleanField(
                verbose_name    = 'is_superuser',
                default         = False
                )
        
        USERNAME_FIELD = 'email'
    
        objects = UserManager()
    
        class Meta:
            db_table = 'users'
    
  • serializers.py
  • の設定
    会員の入力・登録にシリアル化器を作成した.会員登録についてはModelSerializerで作成するのが簡単です.ModelSerializerを使用してログインを作成できますか?という悩みがありましたが、ログイン時に使用する変数はemail、passwordのみなのでニックネーム、is activeなど他の変数がないのでエラーが発生しました.したがって,最終的にはデフォルトのSerializerにのみログインし,場合によってvalidateメソッドを変更した.
    /api/user/serializers.py
    
    from django.contrib.auth.models     import update_last_login
    from django.contrib.auth            import authenticate, get_user_model
    from rest_framework                 import serializers
    from rest_framework_jwt.settings    import api_settings
    
    JWT_PAYLOAD_HANDLER = api_settings.JWT_PAYLOAD_HANDLER
    JWT_ENCODE_HANDLER  = api_settings.JWT_ENCODE_HANDLER
    User = get_user_model()
    
    class UserSignUpSerializer(serializers.ModelSerializer):
        
        class Meta:
            model        = User
            fields       = ['email', 'nickname', 'password']
            extra_kwargs = {
                    'email': {'required':True},
                    'nickname': {'required':True},
                    'password': {'required':True},
                    } 
    
        def create(self, validated_data):
            user = User.objects.create(
                    email       = validated_data['email'],
                    nickname    = validated_data['nickname']
                    )
            user.set_password(validated_data['password'])
            user.save()
            return user
    
    class UserSignInSerializer(serializers.Serializer):
        email       = serializers.CharField(max_length=64)
        password    = serializers.CharField(max_length=128, write_only=True)
        token       = serializers.CharField(max_length=255, read_only=True)
                        
        def validate(self, data):
            email       = data.get('email', None)
            password    = data.get('password', None)
            
            user = authenticate(email=email, password=password)
            if user is None:
                results = {
                        'email':'None'
                        }
                return results
            
            try:
                payload     = JWT_PAYLOAD_HANDLER(user)
                jwt_token   = JWT_ENCODE_HANDLER(payload)
    
                update_last_login(None, user)
    
            except User.DoesNotExist:
                raise serializers.ValidationError(
                    'User with given email and password does not exists'
                )
            
            results = {
                    'email'       : user.email,
                    'access_token': jwt_token
                }
    
            return results 
    
  • views.py
  • の設定
    /api/user/views.py
    from rest_framework                 import generics, status
    from rest_framework.permissions     import AllowAny
    from rest_framework.response        import Response
    
    from .serializers import UserSignInSerializer, UserSignUpSerializer
    from user.models  import User
    
    class UserSignIn(generics.GenericAPIView):
        queryset            = User.objects.all()
        serializer_class    = UserSignInSerializer
        permission_classes  = [AllowAny]
    
        def post(self, request):
            serializer = UserSignInSerializer(data = request.data)
            
            if not serializer.is_valid(raise_exception=True):
                return Response({"message": "Request Body Error."}, status=status.HTTP_409_CONFLICT)
            
            if serializer.validated_data['email'] == 'None':
                return Response({"message": "fail"}, status=status.HTTP_200_OK)
            response = {
                    "access_token": serializer.validated_data['access_token']
                    }
    
            return Response(response, status=status.HTTP_200_OK)
    
    class UserSignUp(generics.CreateAPIView):
        queryset            = User.objects.all()
        serializer_class    = UserSignUpSerializer
        permission_classes  = [AllowAny]
    
    
  • urls.py
  • の設定
    /drf_forum/urls.py
    from django.contrib import admin
    from django.urls    import path, include
    
    urlpatterns = [
        path('admin', admin.site.urls),
        path('api/user', include('api.user.urls')),
        ]
    
    /api/user/urls.py
    from django.urls             import path
    from django.utils.functional import unpickle_lazyobject
    
    from .views import UserSignIn, UserSignUp
    
    app_name = 'users'
    
    urlpatterns = [
            path('/signin', UserSignIn.as_view(), name='user-signin'),
            path('/signup', UserSignUp.as_view(), name='user-signup')
            ]
    
    設定中にJWTに関するエラーが多く発生し、想像以上に時間がかかりました.ただし、会員登録や登録を確認したら良いです.すべて.幸いなことに、全部忘れていないようです.