https://www.youtube.com/watch?v=dkJ3uqkdCcY&t=459s
장고에서 필터와 페이징을 동시에 구현하면 새 페이지에서 필터가 리셋되는 문제가 생김.
Using Django filter and pagination together often breaks the other functionality.
After filtering the category, if you go to the next page, It resets the filtered result.
def HomeView(request):
tutorials = Tutorial.objects.all()
myFilter = TutorialFilter(request.GET, queryset=tutorials)
tutorials = myFilter.qs
return render(request, 'index.html',
{'tutorials': tutorials, 'myFilter': myFilter})
{% for item in tutorials %}
순서 명시해줘야 오류 안남.
class Tutorial(models.Model):
~
class Meta:
ordering = ('-last_updated',)
import django_filters
from django_filters import DateFilter
from .models import Tutorial
from django import forms
class TutorialFilter(django_filters.FilterSet):
DATE_CHOICES = (
('newest', 'Newest'),
('oldest', 'Oldest')
)
date_sort = django_filters.ChoiceFilter(
label ='Sort by Date',
choices =DATE_CHOICES,
method ='filter_by_date',
# widget =forms.Select(attrs={'size': 4})
)
class Meta:
model = Tutorial
fields = {
'title' : ['icontains'],
'instructor': ['icontains'],
'language' : ['exact'],
'difficulty': ['exact'],
}
def filter_by_date(self, queryset, name, value):
expression = 'last_updated' if value == 'oldest' else '-last_updated'
return queryset.order_by(expression)
from .filters import TutorialFilter
def Test(request):
context = {}
# returns a list
filtered_tutorials = TutorialFilter(
request.GET,
queryset=Tutorial.objects.all()
)
context['filtered_tutorials'] = filtered_tutorials
return render(request, 'test_template.html', context=context)
{% for item in filtered_tutorials.qs %}
<form method="get">
{{ filtered_tutorials.form.as_p }}
<input type="submit" value="Press">
</form>
{% for item in filtered_tutorials.qs %}
<h2> {{item.title}} </h2>
{% endfor %}
video 11:09
each page holds 2 objects in one page (from the list)
Paginator(filtered_tutorials.qs, 2)
get pages
request.GET.get('page')
page object which will contain page of entries
paginated_filtered_tutorials.get_page(page_number)
#pagination
paginated_filtered_tutorials = Paginator(filtered_tutorials.qs, 2)
page_number = request.GET.get('page')
tutorial_page_obj = paginated_filtered_tutorials.get_page(page_number)
context['tutorial_page_obj'] = tutorial_page_obj
below is when I apply filter
below is when I click on pagination
2nd result url doesn't include any filter parameters
the only way our view knows how to display entries according to the filter is through the url. And it's not passing the filter parameters
the reason is because in html, href="?page={{ tutorial_page_obj.previous_page_number }}"
this line eliminates filtered url.
tutorial_page_obj
instead of filtered_tutorials.qs
in for loop, otherwise pagination won't work. {% for item in tutorial_page_obj %}
{{item}}
{% endfor %}
print:
Django (3.0) Crash Course Tutorials | Dennis Ivy Build Three Django Projects | Code With Tomi 코딩 1시간만에 배우기 - 파이썬 (ft. 실리콘밸리 엔지니어) | Teccboi Wonie 파이썬(Python) | 동빈나 Python Django Tutorial: Full-Featured Web App | Corey Schafer
{% for item in tutorial_page_obj %}
<h2> {{item.title}} </h2>
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if tutorial_page_obj.has_previous %}
<a href="?page=1">« First</a>
<a href="?page={{ tutorial_page_obj.previous_page_number }}"> Previous</a>
{% endif %}
<span class="current">
Page {{tutorial_page_obj.number}} of {{ tutorial_page_obj.paginator.num_pages}}
</span>
{% if tutorial_page_obj.has_next %}
<a href="?page={{ tutorial_page_obj.next_page_number }}"> Next</a>
<a href="?page={{ tutorial_page_obj.paginator.num_pages }}">»Last</a>
{% endif %}
</span>
</div>
first create three dir, files inside app directory.
1. a directory'templatetags'
2. a file '_ init _.py' (two underscores) -package
3. a file 'appname_extras.py'
Django has built-in template tags, but we are going to create a custom template tags to tackle the problem. by modify existing template tag.
https://docs.djangoproject.com/en/3.1/howto/custom-template-tags/
from django import template
register = template.Library()
if you are using the main app, you need to register templatetags in settings.py
INSTALLED_APPS = [
'hub.apps.HubConfig', ]
need further study..
from django import template
register = template.Library()
@register.simple_tag
def my_url(value, field_name, urlencode=None): #value will pass page number, field_name pass string page and URL
url = f'?{field_name}={value}'
if urlencode:
querystring = urlencode.split('&')
filtered_querystring = filter(lambda p: p.split('=')[0]!=field_name, querystring) #take query string list, take each string and split it by 2, if the first string is equel to the field.
encoded_querystring = '&'.join(filtered_querystring)
url = f'{url}&{encoded_querystring}'
return url
{% load hub_extras %}
< a href="?page=1
->
{% my_url 1 'page' request.GET.urlencode %} ">« First< /a>
< a href="?page={{ tutorial_page_obj.previous_page_number }}
->
{% my_url tutorial_page_obj.previous_page_number 'page' request.GET.urlencode %} "> Previous< /a>
< a href="?page={{ tutorial_page_obj.next_page_number }}
->
{% my_url tutorial_page_obj.next_page_number 'page' request.GET.urlencode %} "> Next</a>
<a href="?page={{ tutorial_page_obj.paginator.num_pages }}
->
{% my_url tutorial_page_obj.paginator.num_pages 'page' request.GET.urlencode %} ">»Last</a>
UnorderedObjectListWarning: Pagination may yield inconsistent results
models.py
class Tutorial(models.Model):
~
class Meta:
ordering = ('-last_updated',)
(remove whitespace when using)
& laquo; - left pointing
& raquo; - right pointing