[DRF] 이것저것

김재연·2022년 9월 21일
0

Watti

목록 보기
10/10
post-thumbnail

1. serializer 외래키 객체 표현 방법

# serializers.py
class UserSimpleSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'email']
        
class ProjectSerializer(serializers.ModelSerializer):
    class Meta:
        model = Project
        fields = '__all__'
    
    def to_representation(self, instance):
        self.fields['user'] = UserSimpleSerializer()
        return super(ProjectSerializer, self).to_representation(instance)

to_representation 없을 때

to_representation 있을 때


2. 유저 자동 저장

- views.py

# views.py
class ProjectViewSet(ModelViewSet):
    serializer_class = ProjectSerializer
    queryset = Project.objects.all()

    def perform_create(self, serializer):
        # print("현재 유저는 : ", self.request.user)
        serializer.save(user=self.request.user)

Header - Authorization : Bearer <jwt토큰>을 담아서 보낸다. (안그러면 AnonymousUser라고 오류남 => AnonymousUser는 유저 객체가 X)

- serializers.py

# serializers.py
class ProjectSerializer(serializers.ModelSerializer):
    class Meta:
        model = Project
        fields = '__all__'
        
    def create(self, validated_data):
        instance, check = Project.objects.get_or_create(
            ...
            user=self.context['request'].user
        )
        return instance

3. url router 설정

Router는 DRF에서 URL 매핑을 편리하게 해준다. 디폴트로 다음과 같이 알아서 연결해준다.

url : /prefix/

  • get : list
  • post : create

url : /prefix/pk/

  • get : retrieve
  • put : update
  • patch : partial_update
  • delete : destroy
from django.urls import include
from .views import *
from rest_framework import routers

router = routers.DefaultRouter()
router.register('prefix1', Prefix1ViewSet)
router.register('prefix2', Prefix2ViewSet)
...

urlpatterns = [
    path("", include(router.urls)),
]

이런식으로 등록하면

이렇게 뜬다.

앱이 여러개일 때 router를 사용하는게 처음이라 살짝 헤맸다.

  • project/urls.py
  • app1/urls.py
  • app2/urls.py

이렇게 앱이 2개 있을 때, 나는 API root 화면에서부터 아래처럼 나오게 router를 사용하고 싶었지만

Api Root
GET /api/
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "app1": "http://127.0.0.1:8000/api/app1/",
    "app2": "http://127.0.0.1:8000/api/app2/"
}

각각 app1, app2로 가는 viewset 자체도 존재하지 않는데다가 그런건 api도 아니니까 그냥 불가능한거였다.

그래서 프로젝트 urls.py에서는

# project/urls.py
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/app1/', include('app1.urls')),
    path('api/app2/', include('app2.urls')),
]

이렇게 앱이름별로 나누고,

각각 해당 앱에서

# app1/urls.py
from rest_framework import routers

router = routers.DefaultRouter()
router.register('app1_api', App1APIViewSet)

# api/app1/
urlpatterns = [
    path("", include(router.urls)),
]
# app2/urls.py
from rest_framework import routers

router = routers.DefaultRouter()
router.register('app2_api', App2APIViewSet)

# api/app2/
urlpatterns = [
    path("", include(router.urls)),
]

이렇게 라우터로 나눠줘야 된다.

이런 느낌?


4. DRF Swagger 작성

(1) APIView

class DuplicateProject(APIView):
    @swagger_auto_schema(
        tags=['project'],
        operation_summary='프로젝트 복제',
        manual_parameters=[
            openapi.Parameter(
                'id',
                openapi.IN_PATH,
                description='복제할 프로젝트의 id',
                required=True,
                default=1, 
                type=openapi.TYPE_INTEGER,
            )
        ]
    )
    def get(self, request, pk):
    	...

(2) Viewset

class ProjectViewSet(ModelViewSet):
    """
    list:
        프로젝트 CRUD - 프로젝트 전체 리스트

        ---

    create:
        프로젝트 CRUD - 프로젝트 생성

        ---

    retrieve:
        프로젝트 CRUD - 프로젝트 조회

        ---

        id : 조회할 프로젝트의 아이디
    
    update:
        프로젝트 CRUD - 프로젝트 수정 (전체)

        ---

        id : 수정할 프로젝트의 아이디

    partial_update:
        프로젝트 CRUD - 프로젝트 수정 (일부)

        ---

        id : 수정할 프로젝트의 아이디

    destroy:
        프로젝트 CRUD - 프로젝트 삭제

        ---

        id : 삭제할 프로젝트의 아이디
    """
    permission_classes = [OnlyOwnerOrPublicRead]
    serializer_class = ProjectSerializer
    queryset = Project.objects.all()

엔터 하고 --- 가 중요

그리고 --- 밑에 쓰면

이렇게 나옴

profile
일기장같은 공부기록📝

0개의 댓글