본문 바로가기

프로그래밍/Django개발(MAC OS)

Django Rest API 서버 만들기 요약 - Day 5 (Filter, Dynamic_filed)

반응형

방 검색을 구현하는 부분을 해보겠습니다.

방을 검색? 필터링 하는 방법들에는 여러가지가 존재합니다.

방의 가격, 침대수, 크기, 위치가 있습니다. 이것을 FBV를 통해서 한번 필터링 해보도록 하겠습니다.

 

우선 각각의 값들을 GET 방식으로 데이터를 전달 받을 것입니다.

@api_view(["GET"])
def room_search(request):
    max_price = request.GET.get("max_price", None)
    min_price = request.GET.get("min_price", None)
    beds = request.GET.get("beds", None)
    bedrooms = request.GET.get("bedrooms", None)
    bathrooms = request.GET.get("bathrooms", None)
    lat = request.GET.get("lat", None)
    lng = request.GET.get("lng", None)
    filter_kwargs = {}
    if max_price is not None:
        filter_kwargs["price__lte"] = max_price
    if min_price is not None:
        filter_kwargs["price__gte"] = min_price
    if beds is not None:
        filter_kwargs["beds__gte"] = beds
    if bedrooms is not None:
        filter_kwargs["bedrooms__gte"] = bedrooms
    if bathrooms is not None:
        filter_kwargs["bathrooms__gte"] = bathrooms
    paginator = OwnPagination()
    try:
        rooms = Room.objects.filter(**filter_kwargs)
    except ValueError:
        rooms = Room.objects.all()    
    results = paginator.paginate_queryset(rooms, request)
    serializer = RoomSerializer(results, many=True)
    return paginator.get_paginated_response(serializer.data)

 그리고 filter_kwargs에서 각각의 값들을 넣어주고, 이를 **로 언패킹하여 filter()를 해주면 됩니다. 

(filter를 저런방식으로 unpacking하는 것을 보고 예전에 나는 하나하나씩 모두 필터해줬는데.... 참 대박이네요.)

 

또한 django에서는 조건 키워드를 넣을 수 있는데 __gt, __lte, __gte 이런 것으로 보다 크면 보다 작으면 이런 방식입니다.

자세한 내용은 아래 블로그에 잘 정리해두셨네요!!

https://brownbears.tistory.com/63

 

[Django] orm

장고에서 제공하는 모델을 사용하기 위해선 from 앱이름.models import 모델명, 모델명1과 같이 선언해야 합니다. 먼저 django orm 사용에서 복잡한 쿼리에 대해 적합하지 않습니다. 예를 들어, 두 테이

brownbears.tistory.com

 

 

그리고 FBV에서 페이지를 나누기 위해서는 아래와 같은 방식으로 하면 됩니다. PageNumberPagination을 생성하여 함수 내에서 해도 되지만 반복적인 사용을 위해서 OwnPagination 클래스를 만들고 PageNumberPagination을 상속받아 사용하면 더욱 편리합니다.

from rest_framework.decorators import api_view
from rest_framework.pagination import PageNumberPagination


class OwnPagination(PageNumberPagination):
    page_size = 20
   
   
@api_view(["GET"])
def room_search(request):
    paginator = OwnPagination()

  ...

 

 

다음은 조금 헷갈리는 내용이지만

Dynamic Field에 대해서 알아보도록 하것입니다. 

Dynamic Field는 언제 사용이 되어야 할까요?? SNS를 예를 들어보면

다른사람들의 포스팅을 볼텐데 이 포스팅이 내가 좋아요을 눌렀는지 안눌렀는지를 알아야겠죠? 이럴때 사용되어지는 것입니다.

User가 어떤 동작을 하는 대부분의 사이트에는 필수적이라고 보시면 될 것 같습니다.

SerializerMethodField를 사용할 것인데요. 이것을 사용하기 위해서는 get_ 변수명을 가지고 하면 됩니다. 그래서 get_is_fav(self,obj): 를 선언해주면 되는 것이죠.

class RoomSerializer(serializers.ModelSerializer):

    user = UserSerializer()
    is_fav = serializers.SerializerMethodField()

    class Meta:
        model = Room
        exclude = ("modified", "created")
        read_only_field = ("user", "id", "created", "updated")

        def validate(self, data):
            if self.instance:
                check_in = data.get("check_in", self.instance.check_in)
                check_out = data.get("check_out", self.instance.check_out)
            else:
                check_in = data.get("check_in")
                check_out = data.get("check_out")
                if check_in == check_out:
                    raise serializers.ValidationError("Not enough time between changes")
            return data


    def get_is_fav(self, obj):
        request = self.context.get("request")
        if request:
            user = request.user
            if user.is_authenticated:
                return obj in user.favs.all()
        return False

 여기서 obj는 model -> Room이 되는 것이고, 이 Room을 현재 보는 유저가 좋아요를 눌렀지를 나타내줘야 하기 때문에 유저 값을 얻어와야합니다. 

어디서 얻어올까요? RoomSerializer를 요청하는 곳에서 얻어와야겠죠? 그 방법은 context에 request를 넘겨주면 됩니다.

#views.py

serializer = RoomSerializer(results, many=True, context={"request": request})

 

조금 헷갈릴 수 있는 부분이라 여러번 복습해야 할 것 같습니다.

반응형