简体   繁体   English

如何根据django admin中的另一个选项字段限制选择字段选项

[英]How to limit choice field options based on another choice field in django admin

I have the following models: 我有以下型号:

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)

In the admin interface when creating a new Demo, after user picks category from the dropdown, I would like to limit the number of choices in the "items" drop-down. 在管理界面中创建新演示时,在用户从下拉列表中选择类别后,我想限制“项目”下拉列表中的选项数量。 If user selects another category then the item choices should update accordingly. 如果用户选择另一个类别,则项目选项应相应更新。 I would like to limit item choices right on the client, before it even hits the form validation on the server. 我想在客户端上限制项目选择,甚至在服务器上进行表单验证之前。 This is for usability, because the list of items could be 1000+ being able to narrow it down by category would help to make it more manageable. 这是为了可用性,因为项目列表可以是1000+,能够按类别缩小它将有助于使其更易于管理。

Is there a "django-way" of doing it or is custom JavaScript the only option here? 是否有“django-way”这样做或自定义JavaScript是唯一的选择?

Here is some javascript (JQuery based) to change the item option values when category changes: 这里有一些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>

You need a view to be called on the /items/ URL that supplies a JSON list of the valid items. 您需要在/ items / URL上调用视图,该视图提供有效项的JSON列表。

You can hook this into your admin by using model admin media definitions . 您可以使用模型管理媒体定义将其挂钩到管理员。

There is django-smart-selects : django-smart-choices

If you have the following model: 如果您有以下型号:

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)

And you want that if you select a continent only the countries are available that are located on this continent and the same for areas you can do the following: 如果您选择一个大陆,只有那些位于该大陆的国家/地区可用,并且您可以执行以下操作:

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)

我认为JavaScript / AJAX将是解决此问题的最佳方法。

You will need to have some kind of non-server based mechanism of filtering the objects. 您将需要某种基于非服务器的过滤对象的机制。 Either that, or you can reload the page when the selection is made (which is likely to be done in JavaScript anyway). 或者,或者您可以在进行选择时重新加载页面(这可能在JavaScript中完成)。

Otherwise, there is no way to get the subset of data from the server to the client. 否则,无法将数据子集从服务器获取到客户端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM