2011-02-07 88 views
3

我有以下型號:Django管理員。顯示分層下拉過濾器

from django.db import models 

class State(models.Model): 
    name = models.CharField(max_length=30) 
    abbreviation = models.CharField(max_length=2) 

    def numberOfCities(self): 
     return self.city_set.count() 

    def __unicode__(self): 
     return u"{0} - {1}".format(self.abbreviation, self.name) 

class City(models.Model): 
    name = models.CharField(max_length=40) 
    state = models.ForeignKey(State) 

    class Meta: 
     verbose_name_plural = 'Cities' 

    def __unicode__(self): 
     return self.name 

class Company(models.Model): 
    name = models.CharField(max_length=60) 
    description = models.CharField(max_length=1000) 
    city = models.ForeignKey(City) 

    class Meta: 
     verbose_name_plural = 'Companies' 

    def __unicode__(self): 
     return self.name; 

正如你可以看到每家公司與城市相關的和你所期望的Django管理生成包含城市的下拉公司創建表單。但爲了改善用戶體驗,我希望用戶首先選擇州,然後城市下拉菜單將填充來自該州的城市。有沒有這樣做的標準方式?

回答

1

您需要創建一個自定義小部件來選擇城市模型(也就是說,您的模型應該FK到城市而不是州),該小部件包含兩個選擇字段,第一個包含Sstates,第二個包含Sstates加載一個國家的選擇(你需要插入一個視圖來返回城市根據國家ID來填充你的城市選擇)。

您應該設置您的小部件媒體內部類指向鏈接兩個選擇的特定.js文件。

在ModelAdmin規範中,將您的字段的小部件設置爲您剛剛創建的自定義小部件,並且它的媒體將自動添加到change_form模板中。

確保您的.js文件查找常規JQuery對象並回退到django.JQuery,這樣您就可以在管理員和整個網站中使用此相同的小部件。

(function($) { 
// Note that this function works only for one widget per page 
$('#state').change(function(){ 
    $('#city').load('/cities_by_state/', {id: this.value}); // the endpoint returns HTML 
}); 
})(JQuery||django.JQuery); 

我已經做了在一個應用程序,我在本地使用爲我的項目類似的東西(可變深度可達三級),將所得溶液結束了有點毛茸茸的,因爲它必須支持每頁多窗口小部件,動態小部件(用於內聯),用於呈現各種形式的小部件的模板標籤等。

+0

我喜歡你的方法,但是我找不到有關如何在文檔上編寫自定義小部件的任何信息。你能否提供一個自定義小部件的例子? – Raphael 2011-02-07 07:37:01

1

彎曲管理員並不容易,但它只是另一個django應用程序,儘管它非常複雜。我通常做這樣的事情:

  1. Make a custom admin template for the model in question(覆蓋change_form.html)。
  2. 製作一個ajax url,返回按狀態id過濾的City小部件。
  3. 當狀態發生變化時,使用類似jQuery的東西來替換City小部件。

Django admin Javascript已經使用jQuery庫。爲了避免與用戶腳本衝突,Django的jQuery命名空間爲django.jQuery。因此,您不必包含第二個副本,可以在更改列表上使用django.jQuery對象並添加/編輯視圖。