목차
Generic views
개발 레퍼런스
DRF를 활용하여 검색 기능을 활용하자!
- 검색 기능의 경우 프론트엔드와 백엔드 모두 처리할 수 있다
- 💾백엔드에서 처리할 때 장점
- 데이터의 리퀘스트와 리스폰스를 백엔드에서 처리하는 것으로 데이터 처리 일관성 유지(개인생각임)
- DRF에서 제공하는 미리 설계된 검색필터링 View를 사용해볼 수 있음
- 🧩프론트엔드에서 처리할 때 장점
- 구글 검색에서 조금 더 효과적인 노출이 가능함(주워 들은 것임)
- 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
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;
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}')`;
}
})
}