разбиение на страницы результатов запроса POST Django

17

Я использую Django Forms для выполнения фильтрации / фасетного поиска через POST, и я хотел бы, чтобы класс paginator Django организовал результаты. Как сохранить исходный запрос при передаче клиента между различными страницами? Другими словами, кажется, что я теряю данные POST, как только передаю запрос GET для другой страницы обратно к моим представлениям. Я видел некоторые рекомендации по использованию AJAX для обновления только блока результатов страницы, но мне интересно, есть ли для этого механизм Django.

Спасибо.

    
задан andyashton 15.02.2010 в 15:31
источник

5 ответов

23

Если вы хотите получить доступ к данным хранилища в более позднем запросе, вам придется его где-то хранить. Django предоставляет несколько способов архивирования:

1) Вы можете использовать сеансы для хранения запроса: Каждый посетитель, который посещает ваш сайт, получит пустой объект сеанса, и вы можете хранить все, что захотите, внутри этого объекта, который действует как dict. Недостаток: один посетитель не может выполнять множественный поиск с разбивкой по страницам одновременно.

2) Использовать файлы cookie: . Если вы установите cookie, который хранится на стороне клиента, браузер добавит данные cookie к каждому запросу, к которому вы можете получить доступ. Файлы cookie более дружественны к серверу, потому что для них на сервере не нужен диспетчер сеансов, но данные, хранящиеся в файлах cookie, видны (и редактируются) клиенту. Недостаток: тот же, что и раньше.

3) Используйте скрытые поля: . Вы можете добавить форму с некоторыми скрытыми полями на странице результатов поиска и сохранить запрос внутри них. Затем клиент отправляет запрос при отправке формы. Недостаток: вы должны использовать форму с кнопками отправки для разбивки на страницы на странице (простые ссылки не работают).

4) Создайте ссылки, содержащие запрос: Вместо использования POST вы также можете использовать GET. Например, у вас может быть ссылка вроде "/search/hello+world/?order=votes" и «paginated links», например "/search/hello+world/2/?order-votes" . Затем запрос можно легко получить из URL-адреса. Недостаток: максимальный объем данных, которые вы можете отправлять через GET, ограничен (но это не должно быть проблемой для простого поиска).

5) Используйте комбинацию . Вы можете захотеть сохранить все данные в сеансе или базе данных и получить к ним доступ через сгенерированный ключ, который вы можете поместить в URL. URL-адреса могут выглядеть так: « /search/029af239ccd23/2" (для второй страницы), и вы можете использовать ключ для доступа к огромному количеству данных, которые вы сохранили ранее. Это устраняет недостаток решения 1, а также решение 4. Новое недостаток: много работы:)

6) Использовать AJAX: С помощью ajax вы можете хранить данные внутри некоторых js-переменных на стороне клиента, которые затем могут передаваться другим запросам. И поскольку ajax будет обновлять список результатов, переменные не теряются.

    
ответ дан tux21b 15.02.2010 в 16:30
источник
  • Спасибо, это полезно. Просто, чтобы распаковать этот вопрос еще немного: это предназначение для класса paginator? Мой просмотр обрабатывает начальную форму поиска, а затем отправляет шаблон объекту paginator.page () для первой страницы. Список результатов генерируется из object_list для этой страницы. Кажется странным, что я не мог отправить его весь набор результатов поиска, и каким-то образом прокручивать его, не перегружая поиск для каждой страницы. Если это предназначение для класса, я могу работать с ним. Просто хочу убедиться, что я не пропущу что-то очевидное. Благодаря! –  andyashton 15.02.2010 в 18:12
  • Да, это предполагаемое использование. Не забывайте, что Django - это веб-инфраструктура, и по своей природе веб-запросы несовместимы. Поэтому, если вы хотите сохранить состояние, вам придется его где-то хранить - и tux21b предоставил вам некоторые варианты относительно того, где. –  Daniel Roseman 15.02.2010 в 20:35
  • Очень полезно, спасибо вам обоим. –  andyashton 15.02.2010 в 21:24
4

Как @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']
""" ... """

Подробнее здесь

    
ответ дан abidibo 19.09.2014 в 15:05
источник
4

Читая очень хороший ответ от 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})

Надеюсь, что это поможет! Если у кого есть какие-либо улучшения, предлагайте, пожалуйста.

    
ответ дан rvnovaes 07.08.2013 в 17:02
источник
0

Вы можете запросить объект запроса, если он ajax, просто request.is_ajax . Таким образом, вы можете обнаружить, будет ли это первый пост-запрос или дополнительные вопросы о следующих страницах.

    
ответ дан gruszczy 15.02.2010 в 15:34
источник
0

Отобразите форму поиска и результаты на одном шаблоне django. Сначала используйте css, чтобы скрыть область отображения результатов. При отправке формы вы можете проверить, не нашли ли поиск какие-либо результаты и скрыть форму поиска с помощью css, если результаты существуют. Если результатов не существует, используйте css, чтобы скрыть область отображения результатов, как раньше. В ваших ссылках на страницы используйте javascript для отправки формы, это может быть так же просто, как document.forms[0].submit(); return false;

Вам нужно будет обработать, как передать номер страницы движку поискового вызова django.

    
ответ дан chefsmart 03.07.2010 в 09:30
источник