Python 分页Django forms POST请求的结果

Python 分页Django forms POST请求的结果,python,django,django-forms,pagination,Python,Django,Django Forms,Pagination,我使用Django表单通过POST进行过滤/分面搜索,我想使用Django的paginator类来组织结果。在不同页面之间传递客户机时,如何保留原始请求?换句话说,当我将另一个页面的GET请求传递回我的视图时,我似乎就丢失了POST数据。我看到一些建议使用AJAX只刷新页面的结果块,但我想知道是否有Django本机机制可以做到这一点 谢谢。您可以询问请求对象是否是ajax,只需request.is_ajax。通过这种方式,您可以检测到这是第一个post请求还是关于下一页的进一步问题。如果您想在以

我使用Django表单通过POST进行过滤/分面搜索,我想使用Django的paginator类来组织结果。在不同页面之间传递客户机时,如何保留原始请求?换句话说,当我将另一个页面的GET请求传递回我的视图时,我似乎就丢失了POST数据。我看到一些建议使用AJAX只刷新页面的结果块,但我想知道是否有Django本机机制可以做到这一点


谢谢。

您可以询问请求对象是否是ajax,只需
request.is_ajax
。通过这种方式,您可以检测到这是第一个post请求还是关于下一页的进一步问题。

如果您想在以后的请求中访问存储数据,您必须将其存储在某个位置。Django提供了几种归档方法:

1)您可以使用来存储查询:每个访问您站点的访问者都会得到一个空会话对象,您可以在该对象中存储任何您想要的内容,这就像一个dict。缺点:单个访问者不能同时进行多个分页搜索

2)使用cookies:如果您设置了存储在客户端的cookie,浏览器会将cookie的数据附加到您可以访问的每个请求中。Cookie对服务器更友好,因为您不需要在服务器上为它们设置会话管理器,但是Cookie中存储的数据对客户端是可见的(并且是可编辑的)。缺点:和以前一样

3)使用隐藏字段:您可以在搜索结果页面上添加带有一些隐藏字段的表单,并将查询存储在其中。然后,客户机将在您提交表单时重新发送查询。缺点:您必须使用带有提交按钮的表单在页面上进行分页(简单链接不起作用)

4)创建包含查询的链接:也可以使用GET而不是POST。例如,您可以有一个链接,如
“/search/hello+world/?order=voces”
和“分页链接”,如
“/search/hello+world/2/?order voces”
。然后可以很容易地从URL检索查询。缺点:通过GET可以发送的最大数据量是有限的(但对于简单的搜索来说,这应该不是问题)

5)使用组合:您可能希望将所有数据存储在会话或数据库中,并通过生成的密钥访问它们,您可以将该密钥放入URL中。URL可能看起来像“
/search/029af239ccd23/2”
(第二页),您可以使用该键访问以前存储的大量数据。这消除了方案1和方案4的缺点。新缺点:工作量大:)


6)使用AJAX:使用AJAX,您可以将数据存储在客户端的一些js变量中,然后将这些变量传递给其他请求。由于ajax只会更新结果列表,所以变量不会丢失。

将搜索表单和结果显示在一个django模板上。最初,使用css隐藏结果显示区域。发布表单时,您可以检查搜索是否返回任何结果,如果结果存在,则使用css隐藏搜索表单。如果结果不存在,请像前面一样使用css隐藏结果显示区域。在分页链接中,使用javascript提交表单,可以像
document.forms[0].submit()一样简单;返回false


您需要处理如何将页码传递给django的分页引擎。

阅读tux21b中非常好的答案后,我决定实现第一个选项,即使用会话存储查询。这是一个搜索房地产数据库的应用程序。以下是视图代码(使用django 1.5):


希望有帮助!如果有人有任何改进建议,欢迎使用。

As@rvnovas,这是一种使用会话解决问题的方法

他的解决方案的缺点是,如果有许多搜索字段,您必须编写许多行代码,并且如果您在结果页中显示搜索表单,则所有字段都将为空,而它们应该保留其值

因此,我宁愿将所有post数据保存在会话中,并在视图的开头强制输入request.post和request.method的值(如果定义了会话):

""" ... """
if not request.method == 'POST':
    if 'search-persons-post' in request.session:
        request.POST = request.session['search-persons-post']
        request.method = 'POST'

if request.method == 'POST':
    form = PersonForm(request.POST)
    request.session['search-persons-post'] = request.POST
    if form.is_valid():
        id = form.cleaned_data['id']
""" ... """

更多信息

我在我的web应用程序中使用get parameters实现了这一点,也许我可以帮助您:

视图.py

class HomeView(ListView):
model = Hotel
template_name = 'index.html'
paginate_by = 10  # if pagination is desired

def get_queryset(self):
   qs = super().get_queryset()
   kwargs = {}
   if 'title' in self.request.GET:
       title = self.request.GET.get('title')
       if title != '':
           kwargs['title__icontains'] = title
   if 'category' in self.request.GET:
       category = self.request.GET.get('category')
       if category:
           kwargs['category_id'] = category
   if 'size' in self.request.GET:
       size = self.request.GET.get('size')
       if size:
           kwargs['size_id'] = size
   if 'service' in self.request.GET:
       service = self.request.GET.get('service')
       if service:
           kwargs['service_id'] = service
   if 'ownership' in self.request.GET:
       ownership = self.request.GET.get('ownership')
       if ownership:
           kwargs['ownership_id'] = ownership
   qs = qs.filter(**kwargs)
   return qs

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    form_init = {}
    form = SearchForm()
    if self.request.GET.items():
        try:
            parameters = self.request.GET.items()
        except KeyError:
            parameters = {}
        for key, value in parameters:
            for field in form.fields:
                if key == field:
                    form_init[key] = value
        form.initial = form_init
    if 'title' in self.request.GET:
       title = self.request.GET.get('title')
       if title != '':
           context.update({
            'title': title
           })
    if 'category' in self.request.GET:
       category = self.request.GET.get('category')
       context.update({
        'category': category
       })
    if 'size' in self.request.GET:
       size = self.request.GET.get('size')
       context.update({
           'size': size
      })
    if 'service' in self.request.GET:
       service = self.request.GET.get('service')
       context.update({
           'service': service
      })
    if 'ownership' in self.request.GET:
       ownership = self.request.GET.get('ownership')
       context.update({
          'ownership': ownership
       })
    context.update({
        'search_form': form
    })
    return context
分页文件html

<div class="row">
  {% if is_paginated %}
  <nav aria-label="...">
    <ul class="pagination">
      {% if page_obj.has_previous %}
        <li class="page-item"><a class="page-link" href="?category={{category}}&size={{size}}&service={{service}}&ownership={{ownership}}&page={{ page_obj.previous_page_number }}">Previous</a></li>
      {% else %}
        <li class="page-item disabled"><span class="page-link">Previous</span></li>
      {% endif %}
      <span class="page-current">
               Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
           </span>
      {% if page_obj.has_next %}
        <li class="page-item"><a class="page-link" href="?category={{category}}&size={{size}}&service={{service}}&ownership={{ownership}}&page={{ page_obj.next_page_number }}">Next</a></li>
      {% else %}
        <li class="page-item disabled"><span class="page-link">Next</span></li>
      {% endif %}
    </ul>
  </nav>
 {% endif %}
</div>

{%if已分页%}
    {%如果页面_obj.has_previous%}
  • {%else%}
  • 上一页
  • {%endif%} 第{{Page_obj.paginator.num_pages}页中的第{{Page_obj.number}页。 {%如果页面_obj.has_next%}
  • {%else%}
  • 下一步
  • {%endif%}
{%endif%}
我的建议是使用会话或cookie存储post请求。如果post数据是敏感的,您应该使用会话来存储它。下面的代码包含我使用会话实现它的逻辑

def index(request):
    is_cookie_set = 0
    # Check if the session has already been created. If created, get their values and store it.
    if 'age' in request.session and 'sex' in request.session: 
        age = request.session['age']
        sex = request.session['sex']
        is_cookie_set = 1
    else:
        # Store the data in the session object which can be used later
        request.session['age'] = age
        request.session['sex'] = sex
    if(request.method == 'POST'):
        if(is_cookie_set == 0): # form submission by the user
            form = EmployeeForm(request.POST)
            sex = form.cleaned_data['sex']
            age = form.cleaned_data['age']
            if form.is_valid():
                result = Employee.objects.all(sex=sex,age_gte=age) # filter all employees based on sex and age
        else: # When the session has been created
            result = Employee.objects.all(sex=sex,age_gte=age)
        paginator = Paginator(result, 20) # Show 20 results per page
        page = request.GET.get('page')
        r = paginator.get_page(page)
        response = render(request, 'app/result.html',{'result':result})    
        return response
    else:
        form = EmployeeForm()
    return render(request,'app/home.html',{'form':form})
您还应该检查post字段是否为空,并根据它更改逻辑。您还可以按照@abidibo的建议将整个post请求存储在会话中


你也可以用cookies来做同样的事情。我已经解释过了

谢谢,这很有帮助。只是想进一步解开这个问题:这是paginator类的预期用途吗?我的视图处理初始搜索表单,然后将模板发送到第一页的paginator.page()对象。结果列表是从该页面的对象列表生成的。奇怪的是,我无法将整个搜索结果集发送给它,并且在不重新提交sea的情况下翻阅它
def index(request):
    is_cookie_set = 0
    # Check if the session has already been created. If created, get their values and store it.
    if 'age' in request.session and 'sex' in request.session: 
        age = request.session['age']
        sex = request.session['sex']
        is_cookie_set = 1
    else:
        # Store the data in the session object which can be used later
        request.session['age'] = age
        request.session['sex'] = sex
    if(request.method == 'POST'):
        if(is_cookie_set == 0): # form submission by the user
            form = EmployeeForm(request.POST)
            sex = form.cleaned_data['sex']
            age = form.cleaned_data['age']
            if form.is_valid():
                result = Employee.objects.all(sex=sex,age_gte=age) # filter all employees based on sex and age
        else: # When the session has been created
            result = Employee.objects.all(sex=sex,age_gte=age)
        paginator = Paginator(result, 20) # Show 20 results per page
        page = request.GET.get('page')
        r = paginator.get_page(page)
        response = render(request, 'app/result.html',{'result':result})    
        return response
    else:
        form = EmployeeForm()
    return render(request,'app/home.html',{'form':form})