www.youtube.com/watch?v=G-Rct7Na0UQ&list=PL-51WBLyFTg2vW-_6XBoUpE7vpmoR3ztO&index=13
이 포스팅은 다음과 같은 youtube 영상을 따라하면서 배운 내용과 학습 내용을 담은 것이다:
- Dennis Ivy - Filter Form Table Search | Django Framework (3.0) Crash Course Tutorials (pt 12)
현재 Django Version 3.1.2 를 쓰고 있다. Django는 파이썬을 쓰는 오픈소스 웹 프레임워크이다. 웹사이트 만들때 주로 쓰며, 간단한 것이 큰 특징이다.
※ 간단한 검색(Search) 기능 구현하기
이번에는 위의 사진에 보여진 것 처럼 product / date created / status / note contains / date created is greater than or equal to / date created is less than or equal to 에 따라서 검색을 하는 것을 구현하려고 한다.
우선 시작하기 전에 powershell에서 django_filter를 설치해주어야 한다.
>>> pip install django_filter
이후, 이 library를 settings.py에 추가를 해준다:
# settings.py
...
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accounts',
'django_filters',
]
...
models.py에서 Order class에 note라는 object를 추가해준다:
# models.py
...
note = models.CharField(max_length=500, null=True)
...
이후 models.py를 수정했으므로 migration을 해주어야한다:
>>> python manage.py makemigrations
...
>>> python manage.py migrate
...
이제는 accounts 폴더에 filters.py를 추가해준다:
# filters.py
import django_filters
from django_filters import DateFilter, CharFilter
from .models import *
class OrderFilter(django_filters.FilterSet):
start_date = DateFilter(field_name='date_created', lookup_expr='gte')
end_date = DateFilter(field_name='date_created', lookup_expr='lte')
note = CharFilter(field_name='note', lookup_expr='icontains')
class Meta:
model = Order
fields = "__all__"
exclude = ['customer', 'products']
여기서 lookup_expr의 경우, filter할때 lookup하는 방식이다. gte의 경우 greater than or equal to (크거나 같은)라는 뜻으로, 그러한 크거나 같은 값을 찾으며 lookup을 한다는 것이다. Lookup_expr의 종류는 여기에 가면 자세히 볼 수 있다.
class Meta의 경우, 이전에 form을 설명할때 설명 했으므로 넘어가도록 하겠다.
views.py의 경우, customer 부분에 다음과 같이 변경시켜준다:
# views.py
...
from django.forms import inlineformset_factory
from .filters import *
...
def customer(request, pk_customer):
customer = Customer.objects.get(id=pk_customer)
orders = customer.order_set.all()
order_count = orders.count()
myFilter = OrderFilter(request.GET, queryset=orders)
orders = myFilter.qs
context = {'customer': customer, 'orders':orders, 'order_count':order_count, 'myFilter':myFilter}
return render(request, 'accounts/customer.html', context)
...
여기서 inlineformset_factory를 import 해주고, .filters에 있는 모든 filter method를 import한다
또한, myFilter = OrderFilter(request.GET, queryset=orders)를 통해 orders의 queryset을 통해서 GET method를 불러일으킨다는 것이다.
orders = myFilter.qs를 통해, 새로운 request를 통해 받은 queryset을 orders에 통과를 시켜주고, 이 orders가 context에 들어가는 orders가 되는 것이다.
이를 모두 추가했다면 처음에 보여줬던 사진이 나타나는 것이다:
하지만 저기에 이제 "Note contains"나 "Date created is greater than or equal to " 또는 "Date created is less than or equal to"를 바꾸고 싶다. 여기서 lookup_expr을 바꾸거나, 아예 다음과 같이 template을 바꾸면 된다:
<div class="row">
<div class="col">
<div class="card card-body">
<form method="get">
Start Date: {{myFilter.form.start_date}}
<button class="btn btn-primary" type="submit">Search</button>
</form>
</div>
</div>
</div>
이렇게 {{myFilter.form.start_date}}처럼 아예 form전체가 아닌 특정 부분만 불러와서 따로 customizing을 하는 방법이 있을 듯 하다.