Django REST Framework/DRF 일반

[DRF] 중첩 url을 만들어 보자 : drf-nested-routers

bluebamus 2024. 1. 5.

 - 이 포스팅은 다음 블로그의 정보를 기반으로 작성한다. drf-nested-routers와 관련된 항목에 버그가 있어 수정을 한다.

   - 참고 : https://jaeseo0519.tistory.com/114

 

 1. 중첩 url (nested url)

   - 만약 다음과 같은 database가 있다고 가정한다.

 

   - 우리가 원하는 시나리오는 다음과 같다. 

      - 특정 id의 pet 테이블을 참조하는 특정 cycle 정보이다.

   - 만들고자 하는 url은 다음과 같다.

/api/pets/{pet_id}/cycles/{cycle_id}/

 

   - 자동으로 생성되는 ModelViewSet 기반의 router는 자동 생성으로 위와 같은 중첩 url을 생성하지 못한다.

   - 직접 as_view를 이용해 아래와 같이 url을 만들어줘야 한다.

# Get list of cycles in a Pet
url(r'^pets/(?P<pet_pk>\d+)/cycles/?$',
views.CycleViewSet.as_view({'get':'list'}), name='pet-cycle-list')

# Get deatil of a cycle in a Pet
url(r'^pets/(?P<pet_pk>\d+)/cycles/(?P<pk>\d+)/?$',
views.CycleViewSet.as_view({'get':'retrieve'}), name='pet-cycle-detail')
class CycleViewSet(viewsets.ModelViewSet):
    """Viewset of cylce"""
    queryset = Cycle.objects.all().select_related(
        'pet'
        ).prefetch_related(
            'regular_cycle'
        )
    serializer_class = CycleSerializer

 

 2. drf-nested-routers 를 사용해 구현하기

   - 참고 : https://github.com/alanjds/drf-nested-routers

from rest_framework_nested import routers

router = SimpleRouter()
router.register('pets', views.PetViewSet)

cycle_router = routers.NestedSimpleRouter(
    router,
    r'pets',
    lookup='pet'
)
cycle_router.register(
    r'cycle',
    views.CycleViewSet,
    basename='pet-cycle'
)

app_name = 'pet'

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

 

   - lookup='pet': 이 매개변수는 상위 리소스(이 경우 'pets' 리소스)를 조회하는 데 사용될 키워드 인수를 지정합니다. 즉, 중첩된 라우터에 대한 뷰 또는 직렬 변환기를 정의할 때 함수 기반 뷰 또는 클래스 기반 뷰에서 상위 리소스에 대한 변수 이름으로 'pet'을 사용하게 됩니다.
   - 예를 들어 CycleViewSet에서 상위 'pet' 리소스에 액세스해야 하는 메서드가 있는 경우 pet을 키워드 인수로 사용할 수 있습니다.

class CycleViewSet(viewsets.ModelViewSet):
    # ...

    def list(self, request, pet, *args, **kwargs):
        # Access the parent 'pet' resource using the 'pet' parameter
        # Your logic here
        pass

 

 

 * 예시로 사용된 코드에 queryset과  get_queryset이 같이 있어서 혼란스러웠다. 두 코드가 정의되면 get_queryset만 사용된다. 

   - 하지만 get_queryset을 정의하지 않았다면, queryset의 캐시 문제로 create와 update에서 갱신된 데이터가 queryset에 반영되지 않는다는 문제가 있다.

   - 해당 문제를 chatbot에게 여러 방법으로 질문하여 오류를 거르고 얻은 결과로 다음과 같은 방법이 있다.

   - save 이후 self.get_queryset()을 호출하면 갱신된 모델 정보를 가져와 queryset을 갱신한다.

      - 해당 방법은 코드로 테스트하지 않았기에 확인이 필요하다.

class MyModelViewSet(viewsets.ModelViewSet):
    serializer_class = MyModelSerializer
    queryset = MyModel

    def create(self, request, *args, **kwargs):
        instance = MyModel.objects.create(**request.data)
        instance.save()

        # Reevaluate the queryset to include the changes
        queryset = self.get_queryset()
        return Response({'message': 'Object created successfully'})

 

 

 - 참고 :

https://medium.com/swlh/using-nested-routers-drf-nested-routers-in-django-rest-framework-951007d55cdc

 

Using Nested Routers DRF-Nested Routers in Django Rest framework

Introduction

medium.com

https://jaeseo0519.tistory.com/114

 

[DRF] Concept part - Mixins, generics, Viewset & router(with. nested router)

목차 1. Mixins 2. Generics APIView 3. Viewset & router 4. action-decorator 5. Nested router Django REST Framework 3.13 -- Classy DRF What is this? Django REST framework is a powerful and flexible toolkit that makes it easy to build Web APIs. It provides

jaeseo0519.tistory.com

https://kimdoky.github.io/django/2018/07/08/drf-Routers/

 

Django REST Framework - Routers

on July 8, 2018 under django 11 minute read Django REST Framework - Routers “Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index… a resourceful

kimdoky.github.io

 

댓글