2010-02-15 5 views
17

Ich verwende Django Forms ein gefiltertes/facettierte Suche via POST zu tun, und ich würde Djangos paginator Klasse wie die Ergebnisse zu organisieren. Wie behalte ich die ursprüngliche Anfrage beim Übergeben des Clients zwischen den verschiedenen Seiten? Mit anderen Worten, es scheint, dass ich die POST-Daten verlieren, sobald ich die GET-Anfrage für eine andere Seite an meine Ansichten zurückgeben. Ich habe einige Empfehlungen zur Verwendung von AJAX gesehen, um nur den Ergebnisblock der Seite zu aktualisieren, aber ich frage mich, ob es einen Django-nativen Mechanismus dafür gibt.die Ergebnisse einer Django Paginieren bildet POST-Anfrage

Danke.

Antwort

23

Wenn Sie die Speicherung von Daten in späteren Anforderung zugreifen möchten, würden Sie es irgendwo speichern. Django bietet mehr Möglichkeiten, dies zu archivieren:

1) Sie sessions verwenden können, um die Abfrage zu speichern: Jeden Besucher, die Ihre Website besucht, wird ein leeres Session-Objekt und Sie können speichern, was Sie in diesem Objekt wünschen, die wirken wie ein Diktat. Nachteil: Ein einzelner Besucher kann nicht gleichzeitig mehrere Suchvorgänge mit Paginierung durchführen.

2) Verwendung von Cookies: Wenn Sie einen Cookie setzen, der auf der Clientseite gespeichert ist, fügt der Browser die Daten des Cookies an jede Anfrage an, auf die Sie zugreifen können. Cookies sind serverfreundlicher, da Sie auf dem Server keinen Sitzungsmanager für sie benötigen, aber die in Cookies gespeicherten Daten sind für den Client sichtbar (und editierbar). Nachteil: wie zuvor.

3) Verwenden Sie versteckte Felder: Sie können ein Formular mit einigen ausgeblendeten Feldern auf Ihrer Suchergebnisseite hinzufügen und die Abfrage darin speichern. Dann sendet der Client die Abfrage erneut, wenn Sie das Formular absenden. Nachteil: Sie müssen ein Formular mit Übermittlungsschaltflächen für die Seitennummerierung auf Ihrer Seite verwenden (einfache Links funktionieren nicht).

4) Erstellen Sie Links, die die Abfrage enthalten: Anstelle von POST können Sie auch GET verwenden. Zum Beispiel könnten Sie einen Link wie "/search/hello+world/?order=votes" und "paginierte Links" wie "/search/hello+world/2/?order-votes" haben. Dann kann die Abfrage leicht von der URL abgerufen werden. Nachteil: Die maximale Datenmenge, die Sie über GET senden können, ist begrenzt (das sollte aber für eine einfache Suche kein Problem sein).

5) Verwenden Sie eine Kombination: Sie möchten möglicherweise alle Daten in einer Sitzung oder einer Datenbank speichern und über einen generierten Schlüssel darauf zugreifen, den Sie in die URL eingeben können. . URLs dann wie "/search/029af239ccd23/2" (für die 2. Seite) aussehen könnte und Sie den Schlüssel verwenden, um eine riesige Menge an Daten zuzugreifen, die Sie vorher gespeichert haben Dies beseitigt den Nachteil der Lösung 1 sowie die der Lösung 4. Neuen Nachteils: viel Arbeit :)

6) Verwenden Sie aJAX: Mit ajax Sie die Daten in einigen js-Variablen auf der Client-Seite speichern kann, die dann zu den anderen Anfragen übergeben kann und da ajax wird nur Ihre Ergebnisliste aktualisieren. Die Variablen gehen nicht verloren.

+0

Danke, das ist hilfreich. Um diese Frage noch ein wenig auszupacken: Ist das der beabsichtigte Einsatz für die Paginator-Klasse? Meine Ansicht verarbeitet das anfängliche Suchformular und sendet dann das Template das paginator.page() - Objekt für die erste Seite. Die Ergebnisliste wird aus der Objektliste für diese Seite generiert. Es ist merkwürdig, dass ich ihm nicht die gesamte Suchergebnismenge senden und irgendwie durchblättern konnte, ohne die Suche für jede Seite erneut einzureichen. Wenn das für den Kurs beabsichtigt ist, kann ich damit arbeiten. Ich möchte nur sicherstellen, dass ich nicht etwas Offensichtliches vermisse. Vielen Dank! – andyashton

+1

Ja, das ist die beabsichtigte Verwendung. Vergessen Sie nicht, dass Django ein Web-Framework ist, und Webanfragen sind aufgrund ihrer Natur nicht zustandsbehaftet. Wenn Sie also den Status beibehalten möchten, müssen Sie ihn irgendwo speichern - und tux21b hat Ihnen einige Möglichkeiten gegeben, wo. –

+0

Sehr hilfreich, danke euch beiden. – andyashton

0

Sie können Request-Objekt fragen, ob es Ajax, einfach request.is_ajax. So können Sie feststellen, ob es sich um eine erste Anfrage oder um weitere Fragen zu den nächsten Seiten handelt.

0

Lassen Sie das Suchformular und die Ergebnisse auf einer einzelnen Django-Vorlage anzeigen Verwenden Sie zunächst css, um den Ergebnisanzeigebereich auszublenden Wenn Sie das Formular senden, können Sie überprüfen, ob Suche ergab keine Ergebnisse und hallo de Suchformular mit CSS wenn Ergebnisse vorhanden sind. Wenn keine Ergebnisse vorhanden sind, verwenden Sie css, um den Ergebnisanzeigebereich wie zuvor auszublenden.Verwenden Sie Javascript in Ihren Seitenumbruch-Links, um das Formular abzuschicken. Dies könnte so einfach sein wie document.forms[0].submit(); return false;

Sie müssen damit umgehen, wie Sie die Seitennummer an djangos Paging-Engine übergeben.

4

Lesen der sehr netten Antwort von tux21b Ich beschloss, die erste Option zu implementieren, d. H. Die Sitzung zum Speichern der Abfrage zu verwenden. Dies ist eine Anwendung, die Immobilien-Datenbanken durchsucht. Hier ist der Ansicht Code (mit 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}) 

Hoffe, dass es hilft, wenn jemand eine Verbesserung zu der Annahme, willkommen!.

4

Als @rvnovaes, eine Möglichkeit, Sitzung zu verwenden, um die Angelegenheit zu lösen.

Der Nachteil seiner Lösung ist, dass, wenn es viele Suchfelder gibt, Sie viele Codezeilen schreiben müssen, und auch wenn Sie das Suchformular auf der Ergebnisseite anzeigen, sind alle Felder leer, während sie beibehalten sollten ihre Werte.

So würde ich lieber all Post-Daten in Sitzung speichern, und zu Beginn der Ansicht den Wert von request.POST und request.method erzwingen, wenn eine Sitzung definiert:

""" ... """ 
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'] 
""" ... """ 

Mehr Infos here

Verwandte Themen