Django - 带分页的多个查询

Django - multiple queries with pagination

从 Django 1.9 更新到 3.2.5 后,我的高级搜索功能不再适用于分页。

我有两个搜索功能。一个在 header 中始终可用以搜索项目名称并包含在我的 base.html 模板中。另一个是高级搜索功能,允许搜索特定标准,例如部门、项目名称、状态等

只要没有分页,一切正常。普通搜索功能支持分页,高级搜索功能不行。

问题似乎是查询的 return,return 是一个以 q=['','',''] 开头的多个查询的列表。因为我的高级搜索中的表单字段有不同的名称,例如qD,qS等列表部分无法正确赋值

url return 在更改页面之前进行高级搜索时:

http://127.0.0.1:8000/advanced_search/?csrfmiddlewaretoken=rzIvrOJdUMHwwxaSR18hy48mPTNCORXjaMYigqELXKRlKzNhBpEjbVSueQGHs7yl&qD=corporate&qC=&qN=&qT=&qS=&qA=&qCD=

url return 换页后进行高级搜索时:

http://127.0.0.1:8000/advanced_search/?page=2&q=(None,%20%27corporate%27,%20%27%27,%20%27%27,%20%27%27,%20%27%27,%20%27%27,%20%27%27)

这里是我的 django 和 html 代码:

views.py

# normal search
def search(request):
    template = 'MAR_Projects/projects.html'
    query = request.GET.get('q')
    if query:    
        filtered_projects = table_projects.objects.filter(Q(Project_Code__icontains=query) | Q(Project_Name__icontains=query))
    else:
        filtered_projects = table_projects.objects.all().order_by('-Project_Creation')
        
    searchResultCount = filtered_projects.count   
    pages = pagination(request, filtered_projects)
    context = {'items': pages[0],
               'page_range': pages[1],
               'query': query,
               'searchResultCount':searchResultCount
               }
    
    return render(request, template, context)

#advanced search
def advanced_search(request):
    template = 'MAR_Projects/advanced_search.html'
    filtered_projects = table_projects.objects.all()
    query = (request.GET.get('q'),request.GET.get('qD'), request.GET.get('qC'), request.GET.get('qN'), request.GET.get('qT'), request.GET.get('qS'), request.GET.get('qA'),
             request.GET.get('qCD'))
    result = False
    for i,q in enumerate(query):
        if q and i== 1:    
            filtered_projects = filtered_projects.filter(Q(Project_Department_id__BUs_Code__icontains = query[i]))
            result = True
        elif q and i== 2:    
            filtered_projects = filtered_projects.filter(Q(Project_Code__icontains = query[i]))
            result = True
        elif q and i== 3:    
            filtered_projects = filtered_projects.filter(Q(Project_Name__icontains = query[i]))
            result = True
        elif q and i== 4:    
            filtered_projects = filtered_projects.filter(Q(Project_Type_id__ProjectType_Code__icontains = query[i]))
            result = True
        elif q and i== 5:    
            filtered_projects = filtered_projects.filter(Q(Project_Status_id__ProjectStatus_code__icontains = query[i]))
            result = True
        elif q and i== 6:    
            filtered_projects = filtered_projects.filter(Q(Project_Assignee_id__Assignee_Name__icontains = query[i]))
            result = True
        elif q and i== 7:    
            filtered_projects = filtered_projects.filter(Q(Project_Creation__icontains = query[i]))
            result = True            
  
    searchResultCount = filtered_projects.count
    pages = pagination(request, filtered_projects)
    context = {'items': pages[0],
               'page_range': pages[1],
               'result': result,
               'query': query,
               'searchResultCount':searchResultCount,
               }
    
    return render(request, template, context)

advanced_search.html 模板

{% extends 'Mar_Projects/base.html' %}
{% load static %}
{% block content %}
{% if user.is_authenticated %}
<h4>Advanced search</h4>
<table class="table table-striped">
  <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">BUs</th>
      <th scope="col">Project Code</th>
      <th scope="col">Name</th>
      <th scope="col">Type</th>
      <th scope="col">Status</th>
      <!-- <th scope="col-sm">Description</th>-->
      <th scope="col">Assignee</th>
      <th scope="col">Creation Date</th>
    </tr>
  </thead>
  <tbody>
    <tr>
    <form method="get" action={% url 'MAR_Projects:advanced_search' %}>
    {% csrf_token %}
      <th scope="row"></th>
      <td><input class="form-control mr-sm-2" type="search" placeholder="Department" aria-label="Department" name='qD' value= {{ request.GET.qD}}></td>
      <td><input class="form-control mr-sm-2" type="search" placeholder="Code" aria-label="Code" name='qC' value= {{ request.GET.qC}}></td>
      <td><input class="form-control mr-sm-2" type="search" placeholder="Name" aria-label="Name" name='qN' value= {{ request.GET.qN}}></td>
      <td><input class="form-control mr-sm-2" type="search" placeholder="Type" aria-label="Type" name='qT' value= {{ request.GET.qT}}></td>
      <td><input class="form-control mr-sm-2" type="search" placeholder="Status" aria-label="Status" name='qS' value= {{ request.GET.qS}}></td>
      <td><input class="form-control mr-sm-2" type="search" placeholder="Assignee" aria-label="Assignee" name='qA' value= {{ request.GET.qA}}></td>
      <td><input class="form-control mr-sm-2" type="search" placeholder="Date" aria-label="Date" name='qCD' value= {{ request.GET.qCD}}></td>
    </tr>
    <tr><td></td><td>{%if result %}{{searchResultCount}} Found{% endif %}</td><td></td><td></td><td></td><td></td><td></td>
    <td><input type="submit" class="btn btn-secondary" value="Search"></td>
    </tr>
    </form>
  
  
  
    {%if result %}
    {%for pj in items%}
    <tr>
      <th scope="row">{{ forloop.counter0 | add:items.start_index }}</th>
      <td>{{pj.Project_Department}}</td>
      <td><a href = '/projects/{{pj.Project_Id}}'>{{pj.Project_Code}}</a></td>
      <td>{{pj.Project_Name}}</td>
      <td>{{pj.Project_Type}}</td>
      <td>{{pj.Project_Status}}</td>
      <!--<td style="max-width:350px;white-space:nowrap; overflow:hidden">{{pj.Project_Description}}</td>
      -->
      <td>{{pj.Project_Assignee}}</td>
      <td>{{pj.Project_Creation}}</td>
    </tr>
    {%endfor%}
  {% endif %}
  </tbody>
  
</table>
<br/>
{%if result %}
{% include 'MAR_Projects/pagination.html' %}
{% endif %}
{% endif %}
{% endblock %}

base.html 模板

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"/>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/open-iconic/1.1.1/font/css/open-iconic-bootstrap.min.css" integrity="sha256-BJ/G+e+y7bQdrYkS2RBTyNfBHpA9IuGaPmf9htub5MQ=" crossorigin="anonymous" />
    <title>{% block title%}Project{%endblock%}</title>
  </head>
  <body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>

  <div class="collapse navbar-collapse" id="navbarSupportedContent">
    {% if user.is_authenticated %}
    <ul class="navbar-nav mr-auto">
      <li class="nav-item active">
        <a class="nav-link" href="{%url 'MAR_Projects:home' %}">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="{%url 'MAR_Projects:projects' %}">Projects Overview</a>
      </li>    
      
    
    <li class="nav-item">
    
        <a class="nav-link" href="{% url 'MAR_Projects:projectCreate' %}">
            <span class="oi oi-plus" aria-hidden="true"></span>&nbsp; Project
        
        </a>
    </li>
    </ul>
    <ul class="navbar-nav">
    <li>
    <form class="form-inline my-2 my-lg-0" method="GET" action = {% url 'MAR_Projects:search-results' %}>
      <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" name='q' value= {{ request.GET.q}}>
      <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
    </form>
    </li>
    <li class="nav-item">
        <a class="btn btn-outline-success my-2 my-sm-0" href="{%url 'MAR_Projects:advanced_search' %}">Adv. Search</a>
    </li>    
    <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ user }}</a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
          <a class="dropdown-item" href="/profile">Profile</a>   
          <div class="dropdown-divider"></div>
          <a class="dropdown-item" href="/logout">Logout</a>
        </div>
      </li>
  
    </ul>  
  </div>
  {% else %}
    <ul class="navbar-nav navbar-right">
    <li class="nav-item">
        <a class="nav-link" href="/login">Login</a>
    </li> 
    </ul>  
  
   {% endif %}
    
</nav>
<br/>
    <div class="container-fluid">
    {% if messages %}
        <div class="span12">
        {% for message in messages %}
            <div class="alert alert-{{ message.level_tag }}" role="alert">
                {{ message|safe }}
            </div>
            
        {% endfor %}
        </div>
    {% endif %}
       {% block content %}
       {% endblock %}
    </div>
    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
  </body>
</html>

花了我一段时间,但我回答了我自己的问题。

它可能不是最好的解决方案,但它确实有效。

在views.py中:

query = (request.GET.get('q'),request.GET.get('qD'), request.GET.get('qC'), request.GET.get('qN'), request.GET.get('qT'), request.GET.get('qS'), request.GET.get('qA'),
         request.GET.get('qCD'))
qDic = {'q':query[0],'qD':query[1],'qC':query[2],'qN':query[3],'qT':query[4],'qS':query[5],'qA':query[6],'qCD':query[7]}
searchResultCount = filtered_projects.count
pages = pagination(request, filtered_projects)
context = {'items': pages[0],
           'page_range': pages[1],
           'result': result,
           'query': qDic,
           'searchResultCount':searchResultCount,
           }

return render(request, template, context)
 

我创建了一个字典 qDic 并插入了我的查询结果。

在我的 pagination.html 模板中:

 {% if items.has_other_pages %}
<div class="col-6 offset-3 text-center pagination-set">
    <nav aria-label="">
        <ul class="pagination justify-content-end">
            {% if items.has_previous %}
                <li class="page-item"><a class="page-link" href="?page={{ items.previous_page_number }} {% if query %}&qD={{ query.qD }}&qC={{ query.qC }}&qN={{ query.qN }}&qT={{ query.qT }}&qS={{ query.qS }}&qA={{ query.qA }}&qCD={{ query.qCD }}{%endif%}">&laquo;</a></li>
            {% else %}
                <li class="page-item disabled"><a class="page-link"><span>&laquo;</span></a></li>
            {% endif %}
            {% for i in page_range %}
                {% if items.number == i %}
                    <li class="page-item active"><a class="page-link" href="#">{{ i }} <span class="sr-only">(current)</span></a></li>
                {% else %}
                    <li class="page-item"><a class="page-link" href="?page={{ i }}{% if query %}&qD={{ query.qD }}&qC={{ query.qC }}&qN={{ query.qN }}&qT={{ query.qT }}&qS={{ query.qS }}&qA={{ query.qA }}&qCD={{ query.qCD }}{%endif%}">{{ i }}</a></li>
                {% endif %}
            {% endfor %}
            {% if items.has_next %}
                <li class="page-item"><a class="page-link" aria-label="Next" href="?page={{ items.next_page_number }}{% if query %}&qD={{ query.qD }}&qC={{ query.qC }}&qN={{ query.qN }}&qT={{ query.qT }}&qS={{ query.qS }}&qA={{ query.qA }}&qCD={{ query.qCD }}{%endif%}">&raquo;</a></li>
            {% else %}
                <li class="page-item disabled"><a class="page-link"><span>&raquo;</span></a></li>
            {% endif %}
        </ul>
    </nav>
 </div>{% endif %}
 

我将查询的字典条目交给了我的 advanced_search.html 模板中的相应查询字段。

希望这是有道理的。

欢迎更好的解决方案。