1.함수 기반 뷰에서 쿼리셋을 적용하는법
내가 아는 방법은 다음과 같다.
- 템플릿의
form
에서input
의name
을 지정한다.
- 뷰에서
request
의GET.get
을 통해 요청에 있는 파라미터의 값을 가져온다.
- 그 값을
filter
함수를 통해 걸러낸다.
View
의 코드는 다음과 같아진다.
def post_list(request:HttpRequest):
#Post의 모든 오브젝트를 가져온다.
qs = Post.objects.all()
#Request에서 검색어를 가져온다. form에서 input의 name에는 q라고 지정이 되어있다.
q = request.GET.get("q")
# 검색어와 일치하는 단어가 들어간 게시물만 걸러서 보여준다.
qs= qs.filter(message__contains=q)
return render(request,"instagram/post_list.html",{"post_list":qs, "q":q})
위와 같이 작성하면, 검색어를 포함한 게시글만 보여지게 된다.
2.클래스 기반 List뷰에서 쿼리셋을 적용하는법
- 함수기반 뷰에서는 컨텍스트가 있어서, 결과값을 원하는 이름으로 집어넣을 수 있었는데, 클래스 기반 뷰에서는 자동으로 처리되는 것들이 많아서, 어떻게 손을 대야할지 모르겠는 경우가 있다.
- 특히 검색처리같은 경우, 쿼리셋을 조작해서 타입이 있는경우, 검색어가 있는경우를 다 조작해야하는데 어떡하지 라는 생각이 들었다.
- 다른 기능들은 일단 제처두고, query_set을 어떻게 내마음대로 조작해서 템플릿에 넘겨줄 수 있는지 알아보자
- 관련 공식문서를 읽어보는것도 좋다.
- 클래스 기반 뷰에서 쿼리셋을 원하는대로 만들기 위해서는
get_queryset
메서드의 오버라이드(재정의)가 필요하다
다음과 같은 코드를 통해 위와 같은 뷰를 구성할 수 잏다.
class PostListView(LoginRequiredMixin, ListView):
model = Post
paginate_by = 10
def get_queryset(self):
qs = super().get_queryset()
q=self.request.GET.get("q","")
qs = qs.filter(message__contains=q)
return qs
post_list = PostListView.as_view()
하지만, 이 쿼리를 실행해보면, 다른 페이지네이션으로 이동했을때, 검색어가 초기화되어, 페이지네이션이 의미가 없어지는 것을 볼 수 있다.
그래서 검색어를 넣어주기 위해 context를 조작하는 방법을 알아봤다.
공식문서를 보니까, 재정의하는 코드가 나와있더라
위와같이 컨텍스트에 새로운 값을 넣기 위해서, context
를 부모클래스의 get_context_data
함수를 통해 가져오고, 그 뒤에 context
[키] = value
형태로 집어넣어서 context
를 다시 반환한다.
그러면 검색어를 다음 페이지로 넘어가서도 저장해 놓을 수 있을 것이다.
하지만 문제가 발생했다.
다음페이지로 넘어가도 검색어 유지가 안되길래 url을 보니까, ?page=1 과 같이 page만 남아있는것을 볼 수있었다.
django-bootstrap5
공식문서를 참조해도 방법이 없길래 chat-gpt를 활용해서 물어보니, extra태그의 사용방법과, extra에서 템플릿 빌드인 필터를 이용해서 쿼리스트링을 추가할 수 있는 방법을 찾았다.
템플릿 코드는 다음과 같다.
{% extends 'instagram/layout.html' %}
{% load bootstrap5 %}
{% block title %}
Instagram /Post List
{% endblock title %}
{%block content %}
<form action="" method="get">
<input type="text" name="q" id="" value="{{ q }}" />
<input type="submit" value="검색" />
</form>
<div class="d-grid gap-2">
<a href="{% url 'instagram:post_new' %}" class="btn btn-primary mt-3 mb-3">새 포스팅</a>
</div>
<table class="table table-bordered table-hover">
<tbody>
{% for post in post_list %}
<tr>
<td>{{post.pk}}</td>
<td>
<a href="{{post.get_absolute_url}}"> {{post.message}} </a>
</td>
<td>
{% if post.photo %}
<img src="{{post.photo.url}}" alt="" width="150px" />
{% else %} no Photo {% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ page_obj }}
# 중요한 부분이 여기다. extra="q=검색어"의 형태로 파라미터에 값을 넣어야 하는데, 태그 내에서
# 컨텍스트에 들어있는 값을 쓰기 위해서는 |add 와같은 필터를 사용해야 한다.
{% bootstrap_pagination page_obj size="small" extra='q='|add:q justify_content="center"%}
{% endblock content %}
https://docs.djangoproject.com/en/3.2/ref/templates/builtins/
결과는 다음과 같다.
이렇게 페이지가 넘어가도 유지되는 모습을 볼 수 있다.
chat gpt에 한 열번은 넘게 다시 물어본것 같다… 말을 지어내거나 하는경우도 있어서 더 헷갈렸는데, 점점 좁혀나가는 식으로 질문하니 결국 알려주긴 하더라
Uploaded by N2T