在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 modelsfrom django.db.models import Qclass 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() 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 chainfrom .models import Bookfrom django.views.generic import ListViewclass 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) queryset_chain = chain( results, ) qs = sorted(queryset_chain, key=lambda instance: instance.pk, reverse=True ) self.count = len(qs) return qs return Book.objects.none()
配置urls
1 2 3 4 5 6 from . import viewsurlpatterns = [ ………… 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 %}