如何在Django Admin中根据另一个选择字段限制选项选择

14 投票
3 回答
8803 浏览
提问于 2025-04-15 11:17

我有以下这些模型:

class Category(models.Model):
    name = models.CharField(max_length=40)

class Item(models.Model):
    name = models.CharField(max_length=40)
    category = models.ForeignKey(Category)

class Demo(models.Model):
    name = models.CharField(max_length=40)
    category = models.ForeignKey(Category)
    item = models.ForeignKey(Item)

在管理界面创建新Demo时,当用户从下拉菜单中选择类别后,我想限制“项目”下拉菜单中的选择数量。如果用户选择了另一个类别,那么项目的选择也应该相应更新。我希望在客户端就限制项目的选择,甚至在服务器进行表单验证之前就完成。这是为了提高用户体验,因为项目列表可能有1000多个,通过类别来缩小选择范围会让管理变得更简单。

有没有什么“django方式”可以做到这一点,还是说只能用自定义的JavaScript呢?

3 个回答

0

你需要有一种不依赖服务器的方式来过滤这些对象。要不然,你可以在选择后重新加载页面(这通常也是用JavaScript来实现的)。

否则,就没有办法从服务器获取到你想要的数据子集到客户端。

7

这里有一个叫做 django-smart-selects 的工具:

假设你有一个这样的模型:

class Location(models.Model)
    continent = models.ForeignKey(Continent)
    country = models.ForeignKey(Country)
    area = models.ForeignKey(Area)
    city = models.CharField(max_length=50)
    street = models.CharField(max_length=100)

如果你希望在选择一个洲的时候,只能看到这个洲上面的国家,而在选择地区的时候也能做到同样的限制,你可以这样做:

from smart_selects.db_fields import ChainedForeignKey 

class Location(models.Model)
    continent = models.ForeignKey(Continent)
    country = ChainedForeignKey(
        Country, 
        chained_field="continent",
        chained_model_field="continent", 
        show_all=False, 
        auto_choose=True
    )
    area = ChainedForeignKey(Area, chained_field="country", chained_model_field="country")
    city = models.CharField(max_length=50)
    street = models.CharField(max_length=100)
10

这里有一些基于JavaScript(使用JQuery)的代码,用来在类别变化时更改项目选项的值:

<script charset="utf-8" type="text/javascript">
  $(function(){
    $("select#id_category").change(function(){
      $.getJSON("/items/",{id: $(this).val(), view: 'json'}, function(j) {
        var options = '<option value="">--------&nbsp;</option>';
        for (var i = 0; i < j.length; i++) {
          options += '<option value="' + j[i].optionValue + '">' + j[i].optionDisplay + '</option>';
        }
        $("#id_item").html(options);
        $("#id_item option:first").attr('selected', 'selected');
      })
      $("#id_category").attr('selected', 'selected');
    })
  })
</script>

你需要一个视图(view),它会在 /items/ 这个网址被调用,并提供一个有效项目的JSON列表。

你可以通过使用模型管理媒体定义将这个功能添加到你的管理后台。

撰写回答