2011-12-20 136 views
2

我正在將一個項目從php轉換到Django,並遇到過濾菜單的問題。我有一個表格:django動態過濾形式

class SearchForm(forms.Form): 
    genus = forms.CharField(max_length=100) 
    # species 
    species = forms.CharField(max_length=100) 
    # island group 
    island_group = forms.ModelChoiceField(queryset=Localitymayor.objects.values_list('islandgroup', flat=True).distinct('islandgroup').exclude(islandgroup="n/a").order_by('islandgroup'), empty_label=_("Not Specified")) 
    # island name 
    island_name = forms.ModelChoiceField(queryset=Localitymayor.objects.values_list('islandname', flat=True).distinct('islandname').exclude(islandname="n/a").order_by('islandname'), empty_label=_("Not Specified")) 

我的模板是沿着線:

<form action="{% url cdrs_search %}" method="post">{% csrf_token %} 
{% for field in form %} 
<div class="fieldWrapper"> 
    {{ field.errors }} 
    {{ field.label_tag }}: {{ field }} 
</div> 
{% endfor %} 
</form> 

現在我要過濾的island_name的取決於island_group選擇,輸出。在我的PHP項目中,我用ajax onChange調用了另一個php腳本。但是,我在Django中如何做到這一點有點失落。由於這是我第一次在Django中使用ajax,因此對於處理這種簡單但通用的過濾菜單問題的最佳實踐方法,我將不勝感激。提前致謝。

+0

爲什麼它會在Django中有所不同?您仍然需要一個調用服務器端視圖的Ajax onChange函數。 – 2011-12-20 19:03:12

回答

0

這裏是來自betspire.com票券形式的代碼修改。這段代碼依賴於jQuery的加載。

這裏有您需要的JavaScript:

function update_select(select, data) { 
     select.find('option').remove(); 
     select.append($('<option value="">-------</option>')); 
     for (var i in data) { 
      select.append($('<option value="'+data[i][0]+'">'+data[i][1]+'</option>')); 
     } 
    } 

    $('select[name=island_group]').live('change', function(e) { 
     $.get(
      '{% url island_name_choices_for_island_group %}', 
      { 
       'island_group': $(this).val(), 
      }, 
      function(data, textStatus, jqXHR) { 
       update_select($('select[name=island_name]'), data); 
      }, 
      'json' 
     ); 
    }); 

添加到URL:

url(
    r'island_name/choices/$', 
    'island_name_choices_for_island_group', { 
    }, 'island_name_choices_for_island_group', 
), 

加入的觀點:

from django.utils import simplejson 

from models import * 

def island_name_choices_for_island_group(request, qs=None): 
    if qs is None: 
     # Change the default QS to your needs 
     # (you didn't specify it) 
     qs = Island.objects.all() 

    if request.GET.get('island_group'): 
     # assuming your Island model has an FK named island_group to model IslandGroup 
     qs = qs.filter(island_group__pk=request.GET.get('island_group')) 

    results = [] 
    for choice in qs: 
     results.append((choice.pk, choice.name)) 

    return http.HttpResponse(simplejson.dumps(results)) 

請讓我知道如果你在任何troubble運行。

+0

嗨,我已經嘗試了一些修改你的代碼,但我仍然無法得到ajax更新菜單。具體而言,我不確定我的html。我可能會向您發送我有的代碼供您查看嗎? – 2011-12-27 13:48:40

+0

首先:ajax視圖中是否存在python錯誤(通過打開url或使用firebug驗證ajax視圖)?第二:是否有任何JavaScript錯誤(使用螢火蟲)?第三:添加「console.log」語句或使用螢火蟲調試JavaScript,並檢查預期的代碼是否運行預期的參數:) – jpic 2011-12-29 10:28:48

+0

好吧 - 我現在工作。雖然我對「qs = None」還不清楚,但是。你能解釋爲什麼這是必要的嗎? – 2011-12-29 15:33:20

1

您需要有一個視圖讓您的ajax腳本點擊以查詢基於組的名稱列表,例如,

# views.py 
def ajax_endpoint(request): 
    # leaving error checking to you 
    group = request.GET.get('group') 
    names_list = avalable_names(group) # some function or db call 
    return HttpResponse(json.dumps(names_list)) 
1

一個選項是在javascript中執行此操作。您可以使用來自jQuery的ajax請求撥打單獨的視圖。這個單獨視圖的工作是根據用戶選擇的island_group處理模型數據(島)名稱的服務器端排序)。然後,您可以使用javascript來使用視圖中的響應重新填充表單。關於如何做到這一點的一些很好的例子可以找到in this blog(它有點密集,但非常有用),in an article on how to do this with javascriptin this tutorial(強烈推薦)。

還有一個很好的SO帖子,解釋了爲什麼需要這樣做,它可能有點兒迂腐,但它有助於在創建過濾表單時爲我澄清事情。請看這個問題的 accepted answer

+0

感謝您的寶貴信息。我會看看我是否可以爲我工作。 – 2011-12-21 08:08:36