You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django无需额外创建国家城市模型实现联动下拉框咨询

实现方案

1. 模型字段定义

不需要给城市字段做特殊关联,直接用CharField存储城市名称即可,替换你代码里的school_city = ??部分:

school_city = models.CharField(max_length=100, verbose_name="学校所在城市")

修改后执行python manage.py makemigrations和python manage.py migrate完成数据库变更。

2. 后端接口开发

django-cities已经内置了国家、城市的预定义模型,你不需要手动创建对应模型,完成django-cities的初始化迁移后直接调用即可。首先编写接口根据传入的国家代码返回对应城市列表:

视图代码

# views.py
from django.http import JsonResponse
from cities.models import City, Country

def get_cities_by_country(request):
    country_code = request.GET.get('country_code')
    if not country_code:
        return JsonResponse({'cities': []})
    country = Country.objects.filter(code=country_code.upper()).first()
    if not country:
        return JsonResponse({'cities': []})
    cities = City.objects.filter(country=country).values('name')
    return JsonResponse({'cities': list(cities)})

路由配置

# 项目/应用的urls.py
from django.urls import path
from . import views

urlpatterns = [
    # 原有路由
    path('api/get_cities/', views.get_cities_by_country, name='get_cities'),
]

3. 前端联动逻辑

在表单渲染模板中加入监听逻辑,选中国家后自动请求接口加载城市选项:

<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <div>
        <label>学校国家:</label>
        {{ form.school_country }}
    </div>
    <div>
        <label>学校城市:</label>
        <select name="school_city" id="id_school_city" required>
            <option value="">请先选择国家</option>
        </select>
    </div>
    <!-- 其他表单字段 -->
    <button type="submit">提交</button>
</form>

<script>
const countrySelect = document.getElementById('id_school_country');
const citySelect = document.getElementById('id_school_city');

countrySelect.addEventListener('change', () => {
    const countryCode = countrySelect.value;
    citySelect.innerHTML = '<option value="">加载中...</option>';
    
    if (!countryCode) {
        citySelect.innerHTML = '<option value="">请先选择国家</option>';
        return;
    }

    fetch(`/api/get_cities/?country_code=${countryCode}`)
        .then(res => res.json())
        .then(data => {
            let html = '<option value="">请选择城市</option>';
            data.cities.forEach(item => {
                html += `<option value="${item.name}">${item.name}</option>`;
            });
            citySelect.innerHTML = html;
        })
        .catch(() => {
            citySelect.innerHTML = '<option value="">加载失败,请重试</option>';
        });
});
</script>

4. 表单验证(可选)

如果需要校验提交的城市是否属于所选国家,可以新增表单类做校验:

# forms.py
from django import forms
from .models import School
from cities.models import City, Country

class SchoolForm(forms.ModelForm):
    class Meta:
        model = School
        fields = '__all__'

    def clean(self):
        cleaned_data = super().clean()
        country = cleaned_data.get('school_country')
        city = cleaned_data.get('school_city')
        if country and city:
            country_ins = Country.objects.filter(code=country.code).first()
            if not City.objects.filter(country=country_ins, name=city).exists():
                raise forms.ValidationError("所选城市不属于当前国家")
        return cleaned_data

内容的提问来源于stack exchange,提问作者Sista-Night

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 20:27:01