Django - 搜索与分页器

在Django中进行搜索,利用Django自带的Q 查询。

配置models

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from django.db import models
from django.db.models import Q


class BookManager(models.Manager):
def search(self, query=None):
qs = self.get_queryset()
# 这里需要查询的类型
if query is not None:
or_lookup = (Q(title__icontains=query) |
Q(content__icontains=query)
)
qs = qs.filter(or_lookup).distinct() # distinct() is often necessary with Q lookups
return qs


class Book(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.CharField(max_length=100)
publisher = models.CharField(max_length=100)
url = models.URLField()

objects = BookManager()

def __str__(self):
return self.title

配置views

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from itertools import chain
from .models import Book
from django.views.generic import ListView



class SearchView(ListView):
# 配置你的模板
template_name = 'search.html'
paginate_by = 30
count = 0

def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['count'] = self.count or 0
context['query'] = self.request.GET.get('q')
return context

def get_queryset(self):
request = self.request
query = request.GET.get('q', None)

if query is not None:
results = Book.objects.search(query)

# combine querysets
queryset_chain = chain(
results,
)
qs = sorted(queryset_chain,
key=lambda instance: instance.pk,
reverse=True)
self.count = len(qs) # since qs is actually a list
return qs
return Book.objects.none() # just an empty queryset as default

配置urls

1
2
3
4
5
6
from . import views

urlpatterns = [
…………
path('search/', views.SearchView.as_view(), name='search'),
]

配置html文件

搜索表单:

1
2
3
4
5
6
7
8
9
10

<form class="navbar-form navbar-left" method="get">
<div class="form-group">
{% csrf_token %}
<input type="text" name="q" data-toggle="popover" class="form-control" value="{{ request.GET.q }}" placeholder="输入你感兴趣的图书或者作者……">
</div>
<button type="submit" class="btn btn-default">搜 索</button>
</form>
<br/>

内容显示:

1
2
3
{% for object in object_list %}
# 这是是搜索内容object
{% endfor %}

分页器在搜索的时候不能直接是page=1之类的, 需要加上&q={{ request.GET.q }}{% endif %}

分页器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

{% if is_paginated %}

{% if page_obj.has_previous %}
<a class="btn btn-outline-info mb-4" href="?page=1{% if request.GET.q %}&q={{ request.GET.q }}{% endif %}">首页</a>
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.previous_page_number }}{% if request.GET.q %}&q={{ request.GET.q }}{% endif %}">上一页</a>
{% endif %}

{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<a class="btn btn-info mb-4" href="?page={{ num }}{% if request.GET.q %}&q={{ request.GET.q }}{% endif %}">{{ num }}</a>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<a class="btn btn-outline-info mb-4" href="?page={{ num }}{% if request.GET.q %}&q={{ request.GET.q }}{% endif %}">{{ num }}</a>
{% endif %}
{% endfor %}

{% if page_obj.has_next %}
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.next_page_number }}{% if request.GET.q %}&q={{ request.GET.q }}{% endif %}">下一页</a>
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.paginator.num_pages }}{% if request.GET.q %}&q={{ request.GET.q }}{% endif %}">页尾</a>
{% endif %}

{% endif %}