Django 管理员。显示分层下拉过滤器

发布于 2024-10-15 22:56:16 字数 958 浏览 1 评论 0原文

我有以下模型:

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 管理员生成包含城市下拉列表的公司创建表单。但为了改善用户体验,我希望用户首先选择州,然后城市下拉列表将填充该州的城市。有这样做的标准方法吗?

I have the following model:

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;

As you can see each company is associated with a city and as you would expect the Django admin generates the company creation form containing a dropdown of cities. But in order to improve the user experience I would like the user to first select the state and then the city dropdown would be populated with cities from that state. Is there a standard way of doing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

江南烟雨〆相思醉 2024-10-22 22:56:16

您需要创建一个自定义小部件来选择城市模型(也就是说,您的模型应该 FK 到城市而不是州),该小部件包含两个选择字段,第一个包含州,第二个包含在选择上一个州的(您需要插入一个视图来根据州 ID 返回城市来填充您的城市选择)。

您应该将您的小部件 Media 内部类设置为链接两个 Select 的特定 .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);

我在我的项目本地使用的应用程序中做了类似的事情(可变深度最多三个级别),最终的解决方案有点毛茸茸的,因为它必须支持每页多个小部件、动态小部件(用于内联)、模板标签以各种形式呈现小部件等。

You need to create a custom widget to pick the City model (that is, your model should FK to City and not to State), this widget contains two Select fields, the first one contains the Sstates and the second one gets loaded on the pick of a State (you will need to plug a view to return Cities based on State ID to populate your City select).

You should set your widgets Media inner class point to the specific .js file chaining both Selects.

In the ModelAdmin specification, set your field's widget to the custom widget you just created and it's media will be automatically added to the change_form template.

Make sure that your .js file looks for your regular JQuery object and falls back to django.JQuery, this way you can use this same widget in the admin and through out your site.

(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);

I've done something similar in an app I use locally for my projects (variable depth up to three levels) and the resulting solution ended up a bit hairy as it had to support multiple widgets per page, dynamic widgets (for inlines), templatetags to render the widget in various forms, etc.

万人眼中万个我 2024-10-22 22:56:16

改变管理员并不容易,但它只是另一个 django 应用程序,尽管是一个非常复杂的应用程序。我通常会这样做:

  1. 制作自定义管理模板对于有问题的模型(覆盖change_form.html)。
  2. 创建一个 ajax url,返回按州 ID 过滤的城市小部件。
  3. 当状态发生变化时,使用 jQuery 之类的东西来替换 City 小部件。

Django admin Javascript 已经使用了 jQuery 库。为了避免与用户脚本冲突,Django 的 jQuery 命名空间为 django.jQuery。因此,您不必包含第二个副本,您可以在更改列表和添加/编辑视图上使用 django.jQuery 对象。

It is not easy to bend the admin, but it is just another django app, albeit a really complex one. I usually do something like this:

  1. Make a custom admin template for the model in question (override the change_form.html).
  2. Make an ajax url that returns the City widget filtered by State id.
  3. Use something like jQuery to replace the City widget when State changes.

Django admin Javascript already makes use of the jQuery library. To avoid conflict with user scripts, Django's jQuery is namespaced as django.jQuery. So you don't have to include a second copy, you can use the django.jQuery object on changelist and add/edit views.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文