2010-02-15 28 views
17

POST aracılığıyla filtrelenmiş/yönlü arama yapmak için Django Forms kullanıyorum ve sonuçları düzenlemek için Django'nun paginator sınıfını kullanmak istiyorum. İstemciyi çeşitli sayfalar arasında geçirirken orijinal isteği nasıl koruyabilirim? Diğer bir deyişle, GET isteğini başka bir sayfanın görünümlerime geri döndüğü anda POST verilerini kaybeder gibi görünüyor. Sadece sayfanın sonuç bloğunu yenilemek için AJAX kullanmak için bazı öneriler gördüm, ama bunu yapmak için bir Django-doğal mekanizması olup olmadığını merak ediyorum.Django formlarının sonuçlarını ele alma POST isteği

Teşekkürler.

cevap

23

Daha sonra talepte bulunan mağaza verilerine erişmek istiyorsanız, bir yere koymanız gerekir. Django bu arşivlemek için çeşitli yollar sunar:

1) Sen sorgu depolamak için sessions kullanabilirsiniz: Her ziyaretçinin boş oturum nesnesi alacak sitenizi ziyaret ve davranan bu nesnenin içinde ne istersen saklayabilirsiniz Bir dict gibi. Geri Çekilme: Tek bir ziyaretçi, aynı anda sayfalama ile birden fazla arama yapamaz.

2) Tanımlama bilgilerini kullan: İstemci tarafında saklanan bir çerezi ayarlarsanız, tarayıcı çerine erişebildiğiniz her istek için tanımlama bilgilerini ekler. Çerezler sunuculara göre daha kolaydır, çünkü sunucuda onlar için oturum yöneticisi gerekmez, ancak çerezlerde saklanan veriler istemciye görünür (ve düzenlenebilir). Dezavantajı: önceki gibi.

3) Gizli alanları kullan: Arama sonucu sayfanızda bazı gizli alanlara sahip bir form ekleyebilir ve sorguyu içlerinde saklayabilirsiniz. Ardından, formu gönderdiğinizde istemci sorguyu yeniden gönderir. Dezavantaj: Sayfanızdaki sayfalara sayfalama için gönder butonlu bir form kullanmalısınız (basit bağlantılar işe yaramaz).

4) Sorgu içeren bağlantılar oluşturun: POST kullanmak yerine GET kullanabilirsiniz. Örneğin, "/search/hello+world/?order=votes" ve "/search/hello+world/2/?order-votes" gibi "paginated links" gibi bir bağlantınız olabilir. Daha sonra sorgu, URL'den kolayca alınabilir. Geri Çekilme: GET üzerinden gönderebileceğiniz maksimum veri miktarı sınırlıdır (Ancak bu, basit bir arama için sorun olmamalıdır).

5) Bir kombinasyon kullanın: Tüm verileri bir oturumda veya veritabanında depolamak ve URL'ye yerleştirebileceğiniz oluşturulmuş bir anahtar aracılığıyla bunlara erişmek isteyebilirsiniz. URL'ler daha sonra "/search/029af239ccd23/2" (2. sayfa) gibi görünebilir ve daha önce sakladığınız büyük miktarda veriye erişmek için anahtarı kullanabilirsiniz. Bu, çözüm 1'in yanı sıra çözüm 1'in dezavantajını ortadan kaldırır. Yeni dezavantaj: Eğer o zaman diğer isteklere geçirilen olabilir istemci tarafında bazı js-değişkenler, iç veri saklayabilir Ve ajax beri sadece sonuç listesini güncelleyecek ajax ile. çok iş :)

6) AJAX kullanın

+0

sayesinde bu yararlıdır. Sadece bu soruyu biraz daha açmak için: paginator sınıfı için amaçlanan kullanım bu mu? Bence ilk arama formu sonra şablonu ilk sayfa için paginator.page() nesnesi gönderir işler. Sonuçlar listesi o sayfa için object_list'ten oluşturulur. Tüm arama sonucu kümesini gönderemem ve garip bir şekilde, her sayfa için aramayı tekrar göndermeden bir sayfa gönderemem garip görünüyor. Bu sınıf için amaçlanan kullanım ise, onunla çalışabilirim. Sadece belli bir şeyi kaçırmadığımdan emin olmak istiyorum. Teşekkürler! – andyashton

+1

Evet, amaçlanan kullanım budur. Django'nun bir web çerçevesi olduğunu ve doğası gereği web isteklerinin durum bilgisi olmadığını unutmayın. Yani eğer eyaleti korumak istiyorsan, onu bir yere saklaman gerekecek - ve tux21b sana nerede olduğuna dair bazı seçenekler verdi. –

+0

Çok yardımcı, ikinize de teşekkürler. – andyashton

0

Eğer ajax ise, sadece request.is_ajax talep nesnesini isteyebilirsiniz. Bu şekilde, ilk gönderi talebi veya sonraki sayfalarla ilgili başka sorular olup olmadığını tespit edebilirsiniz.

0

Arama formunu ve sonuçları tek bir django şablonunda görüntülüyorsunuz.İlk olarak, sonuç görüntüleme alanını gizlemek için css'yi kullanın. arama herhangi bir sonuç döndürdü ve merhaba sonuçlar mevcutsa css ile arama formu. Sonuçlar mevcut değilse, sonuçları önceki gibi görüntülemek için css'yi kullanın.Sayfa numaralandırma formlarında, formu göndermek için javascript kullanın; bu, document.forms[0].submit(); return false;

kadar basit olabilir. Sayfa numarasının django'nun çağrı motoruna nasıl aktarılacağını ele almanız gerekir.

4

Ben sorguyu depolamak için oturumu kullanan ilk seçeneği, yani uygulamaya karar tux21b dan çok güzel bir cevap okunuyor. Bu, gayrimenkul veritabanlarını araştıran bir uygulamadır. !

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}) 

kimse önermek için herhangi bir iyileşme varsa, memnuniyetle karşılanacaktır Umarım yardımcı olur: İşte (Django 1.5 kullanarak) görünümü kodudur. @rvnovaes olarak

4

, meseleyi çözmek için oturumu kullanmak için bir yol.

Çözümünün dezavantajı, çok sayıda arama alanı varsa, çok sayıda kod yazmanız ve sonuç sayfasında arama formunu göstermeniz durumunda, tüm alanların boş kalması gerektiğidir. onların değerleri.

yüzden oldukça oturumda tüm post verileri kaydetmek ve bir oturum tanımlanması durumunda bakış başında request.POST ve request.method değerini zorlardı:

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

diğer bilgiler here