我有一个Django表单,可以从用户那里获取输入值。然后,这些值将用于查询表ResourceBase
,该表最终将返回过滤结果列表。
由于结果可能很长,因此我添加了带有“上一个”和“下一个”按钮的分页功能。我的问题是,当我单击“上一个”或“下一个”按钮时,表单将还原为默认值。并且所有返回的结果都消失了。如何防止这种情况发生?
我认为,当请求不是“ POST”时,由于“ form1 = QueryForm()”,表单将被重置。但是,由于我是Django和Web开发人员的新手,因此我很难提出一个整洁的解决方案。
在views.py中:
def search(request):
if request.method == "POST":
form1 = QueryForm(data=request.POST)
layer_dict = []
if form1.is_valid():
inp_ct = form1.cleaned_data['country']
q1 = ResourceBase.objects.filter(country_name__iexact=inp_ct)
for layer in q1:
down_url = 'xxxxxxx'.format(layer.title)
view_url = 'xxxxxxx'.format(layer.title)
layer_dict.append((layer.title, down_url, view_url))
layer_dict = sorted(layer_dict, key = lambda x:x[0])
paginator = Paginator(layer_dict, 10)
page = request.GET.get('page', 1)
try:
layers = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
layers = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
layers = paginator.page(paginator.num_pages)
context = {'form1': form1, 'layers': layers}
else:
form1 = QueryForm()
context = {'form1': form1}
return render(request, 'my_app/search.html', context)
在search.html中:
<br />
<h3>Pagination Test</h3>
<br /><br/>
<div class="row">
<div class="col-md-4">
<form method="POST">
{% csrf_token %}
<div class="form-controls">
{{ form1|as_bootstrap }}
</div>
<button class="btn btn-primary" type="submit" style="float: right;" title = "Click to search" ><i class="fa fa-search"></i></button>
</form>
<form method="GET">
<button class="btn btn-primary" type="submit" value="Reset" name="Reset" title="Reset all choices">Reset</button>
</form>
</div>
</div>
{% if layers %}
<div class="row">
<div class="col-md-8">
<div id = "search_results" >
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Select</th>
<th scope="col">Layer Name</th>
<th scope="col">Download</th>
<th scope="col">View Layer</th>
</tr>
</thead>
<tbody>
{% for layer in layers %}
<tr>
<td><input class= messageCheckbox type="checkbox" name="checks" value="{{layer.1}}"/></td>
<td>{{layer.0}}</td>
<td><a href="{{layer.1}}" target="_blank"> Download Layer </a></td>
<td><input class="btn btn-primary" onclick="window.open('{{layer.2}}')" id="view" type="button" name="view" value="View"></td>
</tr>
{% endfor %}
<tr>
<td><input type="checkbox" onClick="toggle(this, 'checks')"/> Select All</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<button class="btn btn-primary" type="button" name="download" style="float: left;" onClick= "open_all_links();">Download Selected</button>
</div>
<div class="a_pagination" align="right">
<span class="step-links">
{% if layers.has_previous %}
<a class="btn btn-primary btn-sm" name="prev_page" href="?page={{ layers.previous_page_number }}" role="button">Prev.</a>
{% endif %}
<span class="current" style ="color:#2C689C;font-size:16px;padding:8px;">
page {{ layers.number }} of {{ layers.paginator.num_pages }}
</span>
{% if layers.has_next %}
<a class= "btn btn-primary btn-sm" href="?page={{ layers.next_page_number }}" role="button">Next</a>
{% endif %}
</span>
</div>
</div>
</div>
{% endif %}
<script type="text/javascript" >
.......
</script>
答案 0 :(得分:2)
您无需使用 POST方法将参数传递给views.py
。
请遵循以下示例,并重写您的view
和html form
。
这是用户输入搜索词的一种简单形式:
<form method="get" action="">
<input type="text" name="search4" class="search_input" placeholder="Search" required="required">
<input type="submit" value="Search">
</form>
下一步是您应该检查views.py
中的输入,我们将输入年龄命名为 name =“ search4” ,以便我们使用以下命令检查表单中是否存在任何输入此代码在我们的views.py
中:
from django.db.models import Q
from django.core.paginator import Paginator
def search(request):
query = request.GET.get("search4")
if query:
queryset = ResourceBase.objects.objects.all() # this will get all of your object of your model
results = queryset.filter(Q(country_name__iexact=query)).all()
number_of_objects = results.count() # get the exact number of object to show in your html file
paginator = Paginator(results, 12) # Show 12 contacts per page
page_var = 'page' # this will use for pagination in your html file
page = request.GET.get(page_var) # this will use for pagination in your html file
contacts = paginator.get_page(page) # send only 12 object to your html file to show to user
context = {
"items": contacts,
"key": str(query),
'page': page_var,
"number_of_objects": number_of_objects,
}
return render(request=request, template_name='search.html', context=context, content_type=None, status=None,
using=None)
else:
... # if user didn't enter anything to search
获取并搜索数据库中的用户输入后,应在search.html
文件中将其显示给用户,如下所示:
{% for item in items %}
<div>
<div>
<div class="product_title">{{ item.title }}</div> # show the part that you want the users to see
... # rest of your item parts to show
</div>
</div>
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if items.has_previous %} # check the pagination that if there is perivious pages
<a href="?{{ page }}=1">« first</a>
<a href="?{{ page }}={{ items.previous_page_number }}">previous</a>
{% endif %}
<span class="current">
Page {{ items.number }} of {{ items.paginator.num_pages }} # example of result : Page 1 of 13
</span>
{% if items.has_next %}
<a href="?{{ page }}={{ items.next_page_number }}"</a> # check the pagination that if there is any next or perivious pages
<a href="?{{ page }}={{ items.paginator.num_pages }}">last »</a> # a link to last page
{% endif %}
</span>
{{ pagination }}
这是带有 Paginator 的基本搜索页面,如果您需要其他帮助或问题,我们将很乐意为您提供帮助。
答案 1 :(得分:1)
代码<a class= "btn btn-primary btn-sm" href="?page={{ layers.next_page_number }}" role="button">Next</a>
确实将获取页面,而form1 = QueryForm()
代码将以空格式显示。您在这里的路线正确。
您有两个选择:
1)更改下一个/上一个按钮,使它们位于form1表单内,并发布内容。将它们移到相同的表单标签中可能是一个挑战。
如果您定位现代浏览器,则可以在提交(https://www.w3schools.com/tags/att_button_form.asp)中使用HTML5表单标签。
<form method="POST" id="form1">
{{ form1|as_bootstrap }}
</form>
... outside the form tag, then
<button class="btn btn-primary btn-sm" form="form1" name="next" value="{{ layers.next_page_number }}" role="button">Next</button>
您应该在request.POST
中输入下一个值。
2)从GET参数初始化QueryForm。
form1 = QueryForm(data=request.GET)
,并将表单参数包含在url中。为此,您将需要一些Javascript(例如How to use an input field as query parameter to a destination?),因为Django在用户插入它们之前在渲染时不知道表单中的值。
答案 2 :(得分:1)
您可以将分页链接更改为按钮以提交表单。更详细的答案在这里: How to define which input fields the form has by pressing different buttons?
您可以阅读我对答案的评论。它说明了答案如何有助于分页。
我修改了在https://simpleisbetterthancomplex.com/series/2017/10/09/a-complete-beginners-guide-to-django-part-6.html中找到的分页代码 修改后的分页代码也如下:
<nav aria-label="Topics pagination" class="mb-4">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<button form="my_form" name="page" value="{{page_obj.number|add:'-1'}}" role="button" class="btn btn-link">Previous</button>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link">Previous</span>
</li>
{% endif %}
{% for i in page_obj.paginator.page_range %}
{% if page_obj.number == i %}
<li class="page-item active">
<span class="page-link">
{{ i }}
<span class="sr-only">(current)</span>
</span>
</li>
{% else %}
<li class="page-item">
<button form="my_form" name="page" value="{{i}}" role="button" class="btn btn-link">{{ i }}</button>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<button form="my_form" name="page" value="{{page_obj.number|add:1}}" role="button" class="btn btn-link">Next</button>
</li>
{% else %}
<li class="page-item disabled">
<span class="page-link">Next</span>
</li>
{% endif %}
</ul>
</nav>>