Python 在django管理编辑表单中按国家筛选城市

Python 在django管理编辑表单中按国家筛选城市,python,django,admin,Python,Django,Admin,我正在一个小项目中使用,该项目列出了位置 位置模型如下所示: class Location(models.Model): def __unicode__(self): return self.name name = models.CharField(max_length=200) instagram_id = models.IntegerField(default=0) country = models.CharField(max_length=

我正在一个小项目中使用,该项目列出了位置

位置模型如下所示:

class Location(models.Model):
    def __unicode__(self):
        return self.name

    name = models.CharField(max_length=200)
    instagram_id = models.IntegerField(default=0)
    country = models.CharField(max_length=200)
    city = models.CharField(max_length=200)

    new_city = models.ForeignKey(City, related_name='venuecity', null=True, blank=True)

    latitude = models.DecimalField(max_digits=17, decimal_places=14, default=0)
    longitude = models.DecimalField(max_digits=17, decimal_places=14, default=0)
迁移数据时,“城市”和“新城市”字段是临时的

我的问题是在管理方面,如何按国家筛选城市选择字段?目的是让用户在添加新记录或编辑现有记录时更容易选择正确的城市


我查阅了django的管理文档,但不知道如何操作。

您可以自定义django管理员使用的表单。在应用程序中,创建一个显示所需行为的表单。在这种情况下,您可能需要编写一个重载表单的
\uuuu init\uuu()
方法并动态调整city字段的值的方法。例如:

class LocationAdminForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(LocationAdminForm, self).__init__(*args, **kwargs)
        if self.instance:
            # we're operating on an existing object, not a new one...
            country = self.instance.country
            cities = # get cities from your master countries list...
            self.fields["new_city"] = ChoiceField(choices=cities)
一旦有了工作模型表单,您可以告诉管理员在admin.py中使用它:

class LocationAdmin(admin.ModelAdmin):
    form = LocationAdminForm
管理定制是有文档记录的。一篇关于动态Django表单的古老但仍然主要相关的文章是

要对新记录执行此操作,您需要在前端实现大部分功能。当选择不同的国家时,您将需要Javascript代码来动态检索和更新城市列表。Django应用程序将公开Javascript可以调用的AJAX视图。它将通过国家并返回一个简单的JSON城市对象,它将使用该对象更新表单中的元素


或者,如果更改工作流,则可以使用纯服务器端解决方案。这可以像“向导”一样工作,要求用户首先选择国家。单击next(下一步)查看向导的步骤2,其中包含动态生成的Django表单,如上所述。这可能有用。

我尝试了上述解决方案(@jdl2003),但它不起作用(至少在Django 1.8中是这样),我得到了与@bruno amaral提到的相同的错误。我可以这样解决问题:

#forms.py
from django.forms import ModelForm, ModelChoiceField
from cities_light.models import City

class MyUserAdminForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(MyUserAdminForm, self).__init__(*args, **kwargs)
        if self.instance:
            country = self.instance.country
            cities = country.city_set.all() if country else City.objects.none()
            self.fields['city'] = ModelChoiceField(queryset=cities)

#admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from myapp.forms import MyUserAdminForm

class MyUserAdmin(UserAdmin):
    form = MyUserAdminForm
    UserAdmin.fieldsets += (
        (None, {'fields': ('dob', 'country', 'city')}),
    )
    UserAdmin.list_display += ('country',)

admin.site.register(get_user_model(), MyUserAdmin)

我现在唯一的问题是,城市列表并没有得到动态更新。我需要先保存国家/地区字段,然后更新城市。

您考虑过创建自定义列表过滤器吗?有一种方法可以通过
name
或任何其他字段在管理面板中列出所有条目。我想从这一点开始会有帮助。对不起,伙计们,我现在意识到我不清楚。问题是,当我编辑一个位置时,选择字段将显示世界上所有的城市。理想情况下会有两个选择字段:一个用于国家,另一个用于城市。谢谢@jdl2003,这是一个巨大的帮助。只是在ChoiceField遇到了一个小障碍。我在尝试更新时遇到错误“无法分配”u'2509408:“Location.new_city”必须是“city”实例。至于new records案例,前端解决方案似乎更好。我也在使用autocomplete light应用程序,这可以让用户更容易使用。听起来ChoiceField需要城市对象,而您正在为它提供unicode字符串。您如何在init中构建城市列表?也许可以尝试:City.objects.filter(country\uu code=self.instance.country)。当我这样做时,我会得到一个错误,即City对象不可编辑。所以我在做cities=City.objects.filter(country\u name=self.instance.country).values\u list('id','name'))