DRF Search APIView

김태인·2022년 8월 11일
post-thumbnail

목차

Generic views

개발 레퍼런스

DRF를 활용하여 검색 기능을 활용하자!

  • 검색 기능의 경우 프론트엔드와 백엔드 모두 처리할 수 있다
  1. 💾백엔드에서 처리할 때 장점
    • 데이터의 리퀘스트와 리스폰스를 백엔드에서 처리하는 것으로 데이터 처리 일관성 유지(개인생각임)
    • DRF에서 제공하는 미리 설계된 검색필터링 View를 사용해볼 수 있음
  2. 🧩프론트엔드에서 처리할 때 장점
    • 구글 검색에서 조금 더 효과적인 노출이 가능함(주워 들은 것임)
  • Django Rest Framework에서 제공하는 이미 만들어진 뷰를 활용하여 쉽고 빠르게 코드만 집어넣어서 검색 기능을 완성해보자!

사용법

🔥 generics.ListAPIView

  • Generic View는 미리 만들어진 DRF의 View 기능이다
  • 미리 만들어진 기능을 활용함으로써 직접 로직을 짜는 형태보다 아주 빠르게 구현할 수 있는 장점을 가지고 있다
  • 커스텀 또한 가능
  • ListAPIView는 만들어진 기능이기 때문에 정해진 값을 지정해주어야 함
    • queryset
    • serializer_class
    • filter_backends
    • search_fields
from rest_framework import generics, filters

📌 queryset

  • queryset은 시리얼라이저를 적용할 쿼리셋을 의미한다
  • 검색 리스팅 기능에서 조회할 모델의 쿼리셋을 가져온다

📌 serializer_class

  • serailizer_class는 쿼리셋을 적용할 시리얼라이저를 의미한다
  • 검색 리스팅 기능에서 시리얼라이저를 통해서 데이터를 리턴할 방식을 결정한다

📌 filter_backends

  • filter_backends는 적용할 필터를 의미한다.
  • rest_framework 의 filter 를 사용한다

📌 search_fields

  • search_fields는 검색을 적용해볼 모델 필드를 의미한다
  • 필드를 넣은 항목을 모두 검사해서 값이 존재한다면 검색한 오브젝트를 리턴한다.
  • 쿼리셋의 모델 필드만 작성할 수 있다.

☝ URL 바인딩

  • URL에 generic View에 해당하는 클래스를 as_view()로 작성하자

😁 시리얼라이저

  • 필터링된 데이터는 serializer_class로 지정한 시리얼라이저를 통과하여 데이터를 반환한다
  • 원하는 데이터 값이 만약 아니라면, 시리얼라이저에서 커스텀을 해줄 필요가 있다!

👨‍💻 코드

시리얼라이저

class QuestionSerializer(serializers.ModelSerializer):
    answer = AnswerSerializer(many=True, source="qnaanswer_set", read_only=True)
    user = serializers.SerializerMethodField()

		#기존 이미지 시리얼라이저를 침해하지 않기 위해 새로운 변수명 설정
    image_path = serializers.SerializerMethodField()
    
    def get_user(self, obj):
        return obj.user.username
		
		# 메소드 필드를 활용 get
    def get_image_path(self, obj):
        print(obj.image)
        return "/media/" + str(obj.image)

    class Meta:
        model = QnAQuestionModel
        fields = "__all__"

제너릭 뷰

from rest_framework import status, generics
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters

class QuestionSearchView(generics.ListAPIView):
        queryset = QnAQuestionModel.objects.all().order_by('-created_at')
        serializer_class = QuestionSerializer
        filter_backends = [filters.SearchFilter]
        search_fields = ['user__username', 'title', 'content', 'hashtag']

프론트엔드 Fetch API

//검색기능
async function searchFilter() {
    let inputvalue = document.getElementById("search_input").value;

    const response = await fetch(`${backend_base_url}/qna/list/search?search=${inputvalue}`, {
        method: 'GET',
    })
    const response_json = await response.json();
    const searchedQuestions = response_json;

    // const searchedQuestions = await getSearch();
    console.log(searchedQuestions);
    const element = document.querySelectorAll(".col");
    element.forEach((card)=>card.remove());

    const div_cards = document.getElementsByClassName("cards")[0];

    //검색 값
    searchedQuestions.forEach((question) => {
        const div_count = document.createElement("div");
        div_count.setAttribute("class","count-list");
        div_count.innerText = " 좋아요💕"+ question.like.length+"   댓글💬 "+ question.answer.length;
        div_card_body.appendChild(div_count);
        if(question.image_path == "/media/"){
            imagecard.style.backgroundImage = `url('https://s3.ap-northeast-2.amazonaws.com/gomunity.shop/media/gomunitydefault.jpg')`;
        } else {
            imagecard.setAttribute("style", "backgroundImage");
            imagecard.style.backgroundImage = `url('https://s3.ap-northeast-2.amazonaws.com/gomunity.shop${question.image_path}')`;
        }
    })
    }
profile
코딩이 취미가 되는 그날까지

0개의 댓글