2010-02-15 43 views
17

Tôi đang sử dụng Biểu mẫu Django để thực hiện tìm kiếm lọc/mặt qua POST và tôi muốn lớp người tổ chức của Django tổ chức kết quả. Làm cách nào để giữ nguyên yêu cầu ban đầu khi chuyển ứng dụng khách giữa các trang khác nhau? Nói cách khác, có vẻ như tôi mất dữ liệu POST ngay khi tôi chuyển yêu cầu GET cho một trang khác về lại chế độ xem của tôi. Tôi đã nhìn thấy một số khuyến nghị để sử dụng AJAX để làm mới chỉ khối kết quả của trang, nhưng tôi tự hỏi nếu có một cơ chế Django-native để làm điều này.Phân loại kết quả của yêu cầu POST biểu mẫu Django

Cảm ơn.

Trả lời

23

Nếu bạn muốn truy cập dữ liệu lưu trữ trong yêu cầu sau này, bạn sẽ phải lưu trữ nó ở đâu đó. Django cung cấp nhiều cách để lưu trữ này:

1) Bạn có thể sử dụng sessions để lưu trữ các truy vấn: Mỗi du khách ai truy cập vào trang web của bạn sẽ nhận được một đối tượng session rỗng và bạn có thể lưu trữ bất cứ điều gì bạn muốn bên trong đối tượng này, có tác dụng giống như một dict. Nhược điểm: Một khách truy cập không thể thực hiện nhiều tìm kiếm cùng lúc với phân trang.

2) Sử dụng cookie: Nếu bạn đặt cookie được lưu trữ ở phía máy khách, trình duyệt sẽ thêm dữ liệu của cookie vào từng yêu cầu mà bạn có thể truy cập vào nó. Cookie thân thiện với máy chủ hơn, vì bạn không cần trình quản lý phiên cho chúng trên máy chủ, nhưng dữ liệu được lưu trữ trong cookie hiển thị (và có thể chỉnh sửa) cho máy khách. Nhược điểm: giống như trước đây.

3) Sử dụng trường ẩn: Bạn có thể thêm biểu mẫu với một số trường ẩn trên trang kết quả tìm kiếm của bạn và lưu truy vấn bên trong chúng. Sau đó, khách hàng sẽ gửi lại truy vấn bất cứ khi nào bạn gửi biểu mẫu. Nhược điểm: Bạn phải sử dụng một biểu mẫu với các nút gửi để phân trang trên trang của bạn (các liên kết đơn giản sẽ không hoạt động).

4) Tạo liên kết chứa truy vấn: Thay vì sử dụng POST, bạn cũng có thể sử dụng GET. Ví dụ: bạn có thể có liên kết như "/search/hello+world/?order=votes" và "liên kết được phân trang" như "/search/hello+world/2/?order-votes". Sau đó, truy vấn có thể dễ dàng được truy xuất từ ​​URL. Nhược điểm: Lượng dữ liệu tối đa bạn có thể gửi qua GET bị giới hạn (Nhưng đó không phải là vấn đề đối với tìm kiếm đơn giản).

5) Sử dụng kết hợp: Bạn có thể lưu trữ tất cả dữ liệu trong phiên hoặc cơ sở dữ liệu và truy cập chúng thông qua khóa được tạo mà bạn có thể đặt trong URL. Sau đó, URL có thể trông giống như "/search/029af239ccd23/2" (đối với trang thứ 2) và bạn có thể sử dụng khóa để truy cập một lượng lớn dữ liệu mà bạn đã lưu trữ trước đó. Điều này giúp loại bỏ nhược điểm của giải pháp 1 cũng như giải pháp của giải pháp 4. Hạn chế mới: nhiều việc :)

6) Sử dụng AJAX: với ajax bạn có thể lưu trữ dữ liệu bên trong một số js-biến trên các mặt hàng, sau đó có thể truyền cho các yêu cầu khác Và kể từ ajax sẽ chỉ cập nhật danh sách kết quả của bạn. , các biến không bị mất

+0

Cảm ơn, điều này hữu ích. Chỉ cần giải nén câu hỏi này thêm một chút: đây có phải là mục đích sử dụng cho lớp paginator không? Chế độ xem của tôi xử lý biểu mẫu tìm kiếm ban đầu, sau đó gửi mẫu đối tượng paginator.page() cho trang đầu tiên. Danh sách kết quả được tạo từ object_list cho trang đó. Có vẻ kỳ quặc là tôi không thể gửi toàn bộ tập kết quả tìm kiếm, và bằng cách nào đó trang qua nó mà không gửi lại tìm kiếm cho mọi trang. Nếu đó là mục đích sử dụng cho lớp, tôi có thể làm việc với nó. Chỉ muốn chắc chắn rằng tôi không bỏ lỡ điều gì đó hiển nhiên. Cảm ơn! – andyashton

+1

Có, đó là mục đích sử dụng. Đừng quên rằng Django là một khuôn khổ web, và theo yêu cầu web tự nhiên của họ không phải là nhà nước. Vì vậy, nếu bạn muốn giữ trạng thái, bạn sẽ phải lưu trữ nó ở đâu đó - và tux21b đã cho bạn một số tùy chọn về vị trí. –

+0

Rất hữu ích, cảm ơn cả hai. – andyashton

0

Bạn có thể yêu cầu đối tượng yêu cầu nếu đó là ajax, chỉ cần request.is_ajax. Bằng cách này, bạn có thể phát hiện, cho dù đó là yêu cầu đăng bài đầu tiên hoặc các câu hỏi khác về các trang tiếp theo.

0

Có biểu mẫu tìm kiếm và kết quả hiển thị trên một mẫu django duy nhất. Ban đầu, hãy sử dụng css để ẩn khu vực hiển thị kết quả. tìm kiếm trả lại bất kỳ kết quả nào và hi de các hình thức tìm kiếm với css nếu kết quả tồn tại. Nếu kết quả không tồn tại, hãy sử dụng css để ẩn vùng hiển thị kết quả như trước.Trong các liên kết phân trang của bạn, hãy sử dụng javascript để gửi biểu mẫu, điều này có thể đơn giản như document.forms[0].submit(); return false;

Bạn sẽ cần xử lý cách chuyển số trang tới công cụ phân trang của django.

4

Đọc câu trả lời rất hay từ tux21b Tôi quyết định triển khai tùy chọn đầu tiên, tức là sử dụng phiên để lưu trữ truy vấn. Đây là một ứng dụng tìm kiếm cơ sở dữ liệu bất động sản. Đây là mã xem (sử dụng 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}) 

Hy vọng điều đó sẽ hữu ích!

4

Là @rvnovaes, một cách để sử dụng phiên để giải quyết vấn đề. Hạn chế của giải pháp của anh là nếu có nhiều trường tìm kiếm bạn phải viết nhiều dòng mã, và nếu bạn hiển thị biểu mẫu tìm kiếm trong trang kết quả, tất cả các trường sẽ trống, trong khi chúng nên giữ giá trị của chúng.

Vì vậy, tôi thà lưu tất cả các dữ liệu bài trong phiên, và vào lúc bắt đầu quan điểm buộc các giá trị của request.POST và request.method nếu một phiên được định nghĩa:

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

Thông tin thêm here

Các vấn đề liên quan