Django之搜索和保存搜索条件

一.搜索

需求:根据书名或者作者名字来进行搜索:

html文件:
地址:html

<form class="form-inline">
  <div class="form-group">
      <select name="search_field" id="search_field" class="form-control">
          <option value="title__contains">书名</option>
          <option value="authors__name__contains">作者</option>
      </select>
  </div>
  <div class="form-group">
    <input type="text" class="form-control" name="kw" placeholder="content">
  </div>
  <button type="submit" class="btn btn-default">搜索</button>
</form>

效果:
在这里插入图片描述
后端通过获取前端选择的内容和输入的内容来进行查询:

#当前页
page_num = request.GET.get('page')
req_path = request.path

search_field = request.GET.get('search_field')
kw = request.GET.get('kw')

if kw:
	#如果kw有值就进行搜索返回
    book_list = models.Book.objects.filter(**{search_field:kw}) #这种只能进行并且的查询,or查询不能应用
    优化:
    q_obj = Q()  #实例化Q对象
    q_obj.connector = 'or'   #默认是and
    q_obj.children.append((search_field,kw))  
    # q_obj.children.append((search_field2,kw2))  # 和上面一个就是或的关系
    book_list = models.Book.objects.filter(q_obj)
else:
	#如果没有就返回所有 
    book_list = models.Book.objects.all()
#这样有没有内容都会进行分页

#总数
page_num_count = book_list.count()  
 
#分页内容
page_obj = MyPage(page_num,page_num_count,req_path,5,10,get_data)
page_html = page_obj.page_html()

book_data = book_list[page_obj.start_num:page_obj.end_num]
return render(request, 'manytable/show_book.html',{'book_data': book_data, 'page_html': page_html})

这里测试的时候会发现一个问题,搜索结果很多的时候,点击下一页并不是带有搜索结果的下一页,而是全部内容的第二页:
在这里插入图片描述
解决办法:

urlencode:会获取查询参数并以&拼接成一个字符串
get_data = request.GET.urlencode()
print(get_data) #结果:search_field=title__contains&kw=123

分页中使用:

for i in page_num_range:  #起始页
    if self.page_num == i:
        page_html += '''<li class="active"><a href="{0}?{1}&page={2}">{3}</a></li>'''.format(self.req_path,self.get_data,i,i)
    else:
        page_html += '''<li><a href="{0}?{1}&page={2}">{3}</a></li>'''.format(self.req_path,self.get_data,i,i)

这样是解决问题了,但是后面多了很多page:
原因分析:urlencode获取到page之后分页中又拼接了page,这就会你点击一次页码就会在后面添加一个page。在这里插入图片描述
解决办法:
第一种:判断一下如果有page就替换掉

page_html += '''<li><a href="?{0}page={1}">{1}</a></li>'''.format(re.sub(r'page=\d+','',self.get_data) if 'page=' in self.get_data else self.get_data + '&',i)

第二种:将request.GET对象传到分页中

get_data = request.GET

分页中使用的时候添加一个page=当前页,在页码中使用urlencode()

for i in page_num_range:
    if self.page_num == i:
        self.get_data['page'] = i
        page_html += '''<li class="active"><a href="{0}?{1}">{2}</a></li>'''.format(self.req_path,self.get_data.urlencode(),i)
    else:
        self.get_data['page'] = i
        page_html += '''<li><a href="{0}?{1}">{2}</a></li>'''.format(self.req_path,self.get_data.urlencode(),i)

报错:This QueryDict instance is immutable
意思是:这个QueryDict实例是不可变的
在这里插入图片描述
解决办法:

get_data = request.GET.copy()
将request.GET换成request.GET.copy()或者使用copy模块

源码分析:
在这里插入图片描述
使用copy之后会调用内部的__deepcopy__方法将mutable=True:
在这里插入图片描述
结果,可以看到下一页的页码标签是带有搜索结果的:
在这里插入图片描述

续更…

猜你喜欢

转载自blog.csdn.net/qq_39253370/article/details/106097955