출처: https://meyouus.tistory.com/64 [정보 공유 - For Me For You For Us]
본문으로 바로가기

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

 

이후, 이 librarysettings.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 classnote라는 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_factoryimport 해주고, .filters에 있는 모든 filter methodimport한다

또한, myFilter = OrderFilter(request.GET, queryset=orders)를 통해 ordersqueryset을 통해서 GET method를 불러일으킨다는 것이다.

orders = myFilter.qs를 통해, 새로운 request를 통해 받은 querysetorders에 통과를 시켜주고, 이 orderscontext에 들어가는 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을 하는 방법이 있을 듯 하다.