分离Django的结果形成POST请求

and*_*ton 18 python django pagination django-forms

我正在使用Django Forms通过POST进行过滤/分面搜索,我想让Django的paginator类来组织结果.在各个页面之间传递客户端时,如何保留原始请求?换句话说,一旦我将另一个页面的GET请求传递回我的视图,我似乎就丢失了POST数据.我已经看到一些建议使用AJAX只刷新页面的结果块,但我想知道是否有一个Django本机机制来执行此操作.

谢谢.

tux*_*21b 25

如果要在以后的请求中访问商店数据,则必须将其存储在某处.Django提供了几种存档方式:

1)您可以使用会话来存储查询:访问您站点的每个访问者都将获得一个空的会话对象,您可以在此对象中存储您想要的任何内容,其行为类似于dict.缺点:单个访问者不能同时进行多个分页搜索.

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

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

4)创建包含查询的链接:您也可以使用GET,而不是使用POST.例如,您可以使用类似链接"/search/hello+world/?order=votes"和"分页链接"之类的"/search/hello+world/2/?order-votes".然后可以从URL轻松检索查询.缺点:您可以通过GET发送的最大数据量是有限的(但这不应该是简单搜索的问题).

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

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


rvn*_*aes 6

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

def main_search(request):
    search_form = UserSearchForm()
    return render(request, 'search/busca_inicial.html', {'search_form': search_form})


def result(request):
    if request.method == 'POST':
        search_form = UserSearchForm(request.POST)
        if search_form.is_valid():
            # Loads the values entered by the user on the form. The first and the second
            # are MultiChoiceFields. The third and fourth are Integer fields
            location_query_list = search_form.cleaned_data['location']
            realty_type_query_list = search_form.cleaned_data['realty_type']
            price_min = search_form.cleaned_data['price_min']
            price_max = search_form.cleaned_data['price_max']
            # Those ifs here populate the fields with convenient values if the user
            # left them blank. Basically the idea is to populate them with values
            # that correspond to the broadest search possible.
            if location_query_list == []:
                location_query_list = [l for l in range(483)]
            if realty_type_query_list == []:
                realty_type_query_list = [r for r in range(20)]
            if price_min == None:
                price_min = 0
            if price_max == None:
                price_max = 100000000
            # Saving the search parameters on the session
            request.session['location_query_list'] = location_query_list
            request.session['price_min'] = price_min
            request.session['price_max'] = price_max
            request.session['realty_type_query_lyst'] = realty_type_query_list
    # making a query outside the if method == POST. This logic makes the pagination     possible.
    # If the user has made a new search, the session values would be updated. If not,
    # the session values will be from the former search. Of course, that is what we want  because
    # we want the 'next' and 'previous' pages correspond to the original search
    realty_list_result =    FctRealtyOffer.objects.filter(location__in=request.session['location_query_list']
                                                    ).filter(price__range=(request.session['price_min'], request.session['price_max'])
                                                   ).filter(realty_type__in=request.session['realty_type_query_lyst'])
    # Here we pass the list to a table created using django-tables2 that handles sorting
    # and pagination for us
    table = FctRealtyOfferTable(realty_list_result)
    # django-tables2 pagination configuration
    RequestConfig(request, paginate={'per_page': 10}).configure(table)

    return render(request, 'search/search_result.html', {'realty_list_size': len(realty_list_result),
                                                      'table': table})
Run Code Online (Sandbox Code Playgroud)

希望它有所帮助!如果有人有任何改进建议,欢迎.


abi*_*ibo 5

作为@rvnovaes,一种使用会话解决问题的方法。

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

因此,我宁愿将所有发布数据保存在会话中,并且在视图的开头强制使用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']
""" ... """
Run Code Online (Sandbox Code Playgroud)

更多信息在这里