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

如何在Django CRUD应用中创建关联下拉列表(求完整代码)

Django CRUD 应用完整实现(关联州/城市 + 水平表单布局)

以下是满足需求的完整代码实现,包含州与城市的联动、水平表单布局及完整的CRUD功能:


1. 项目初始化(若未完成)

执行以下命令创建项目和应用:

django-admin startproject crud_project
cd crud_project
python manage.py startapp company

将company应用添加到crud_project/settings.py的INSTALLED_APPS中:

INSTALLED_APPS = [
    # 原有应用
    'company',
]

2. 模型定义 (company/models.py)

定义关联的州、城市及公司模型:

from django.db import models

class State(models.Model):
    name = models.CharField(max_length=100, unique=True)

    def __str__(self):
        return self.name

class City(models.Model):
    state = models.ForeignKey(State, on_delete=models.CASCADE, related_name='cities')
    name = models.CharField(max_length=100)

    class Meta:
        unique_together = ('state', 'name')

    def __str__(self):
        return self.name

class Company(models.Model):
    company_name = models.CharField(max_length=200)
    dob = models.DateField()
    date_time = models.DateTimeField()
    state = models.ForeignKey(State, on_delete=models.PROTECT)
    city = models.ForeignKey(City, on_delete=models.PROTECT)

    def __str__(self):
        return self.company_name

执行迁移命令:

python manage.py makemigrations
python manage.py migrate

3. 表单定义 (company/forms.py)

创建支持联动和样式的模型表单:

from django import forms
from .models import Company, State, City

class CompanyForm(forms.ModelForm):
    class Meta:
        model = Company
        fields = ['company_name', 'dob', 'date_time', 'state', 'city']
        widgets = {
            'dob': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
            'date_time': forms.DateTimeInput(attrs={'type': 'datetime-local', 'class': 'form-control'}),
            'company_name': forms.TextInput(attrs={'class': 'form-control'}),
            'state': forms.Select(attrs={'class': 'form-control', 'id': 'state-select'}),
            'city': forms.Select(attrs={'class': 'form-control', 'id': 'city-select'}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 编辑页面时,自动加载对应州的城市
        if self.instance.pk:
            state_id = self.instance.state_id
            self.fields['city'].queryset = City.objects.filter(state_id=state_id)
        else:
            self.fields['city'].queryset = City.objects.none()

4. 视图函数 (company/views.py)

实现CRUD逻辑及AJAX城市加载接口:

from django.shortcuts import render, get_object_or_404, redirect
from django.http import JsonResponse
from .models import Company, State, City
from .forms import CompanyForm

def company_list(request):
    companies = Company.objects.all()
    return render(request, 'company/company_list.html', {'companies': companies})

def company_create(request):
    if request.method == 'POST':
        form = CompanyForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('company_list')
    else:
        form = CompanyForm()
    return render(request, 'company/company_form.html', {'form': form})

def company_update(request, pk):
    company = get_object_or_404(Company, pk=pk)
    if request.method == 'POST':
        form = CompanyForm(request.POST, instance=company)
        if form.is_valid():
            form.save()
            return redirect('company_list')
    else:
        form = CompanyForm(instance=company)
    return render(request, 'company/company_form.html', {'form': form})

def company_delete(request, pk):
    company = get_object_or_404(Company, pk=pk)
    if request.method == 'POST':
        company.delete()
        return redirect('company_list')
    return render(request, 'company/company_confirm_delete.html', {'company': company})

# AJAX接口:根据州ID加载对应城市
def load_cities(request):
    state_id = request.GET.get('state_id')
    cities = City.objects.filter(state_id=state_id).order_by('name')
    return JsonResponse(list(cities.values('id', 'name')), safe=False)

5. URL配置

项目URL (crud_project/urls.py)

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('company.urls')),
]

应用URL (company/urls.py)

创建该文件并添加:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.company_list, name='company_list'),
    path('create/', views.company_create, name='company_create'),
    path('update/<int:pk>/', views.company_update, name='company_update'),
    path('delete/<int:pk>/', views.company_delete, name='company_delete'),
    path('load-cities/', views.load_cities, name='load_cities'),
]

6. 模板文件

创建templates/company目录,添加以下模板:

company_list.html(列表页面)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>公司列表</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-4">
    <h2>公司列表</h2>
    <a href="{% url 'company_create' %}" class="btn btn-primary mb-3">添加新公司</a>
    <table class="table table-striped">
        <thead>
            <tr>
                <th>公司名称</th>
                <th>成立日期</th>
                <th>记录时间</th>
                <th>所属州</th>
                <th>所属城市</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            {% for company in companies %}
            <tr>
                <td>{{ company.company_name }}</td>
                <td>{{ company.dob }}</td>
                <td>{{ company.date_time }}</td>
                <td>{{ company.state.name }}</td>
                <td>{{ company.city.name }}</td>
                <td>
                    <a href="{% url 'company_update' company.pk %}" class="btn btn-sm btn-info">编辑</a>
                    <a href="{% url 'company_delete' company.pk %}" class="btn btn-sm btn-danger">删除</a>
                </td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
</div>
</body>
</html>

company_form.html(创建/编辑共用,水平布局)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>{% if form.instance.pk %}编辑公司{% else %}添加公司{% endif %}</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-4">
    <h2>{% if form.instance.pk %}编辑公司{% else %}添加新公司{% endif %}</h2>
    <form method="post">
        {% csrf_token %}
        <!-- 第一行:公司名称、成立日期、记录时间 -->
        <div class="form-row">
            <div class="form-group col-md-4">
                <label for="{{ form.company_name.id_for_label }}">公司名称</label>
                {{ form.company_name }}
                {% if form.company_name.errors %}
                    <small class="text-danger">{{ form.company_name.errors.0 }}</small>
                {% endif %}
            </div>
            <div class="form-group col-md-4">
                <label for="{{ form.dob.id_for_label }}">成立日期</label>
                {{ form.dob }}
                {% if form.dob.errors %}
                    <small class="text-danger">{{ form.dob.errors.0 }}</small>
                {% endif %}
            </div>
            <div class="form-group col-md-4">
                <label for="{{ form.date_time.id_for_label }}">记录时间</label>
                {{ form.date_time }}
                {% if form.date_time.errors %}
                    <small class="text-danger">{{ form.date_time.errors.0 }}</small>
                {% endif %}
            </div>
        </div>
        <!-- 第二行:州、城市 -->
        <div class="form-row">
            <div class="form-group col-md-6">
                <label for="{{ form.state.id_for_label }}">所属州</label>
                {{ form.state }}
                {% if form.state.errors %}
                    <small class="text-danger">{{ form.state.errors.0 }}</small>
                {% endif %}
            </div>
            <div class="form-group col-md-6">
                <label for="{{ form.city.id_for_label }}">所属城市</label>
                {{ form.city }}
                {% if form.city.errors %}
                    <small class="text-danger">{{ form.city.errors.0 }}</small>
                {% endif %}
            </div>
        </div>
        <button type="submit" class="btn btn-primary">保存</button>
        <a href="{% url 'company_list' %}" class="btn btn-secondary ml-2">取消</a>
    </form>
</div>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function() {
    // 监听州选择变化,动态加载对应城市
    $('#state-select').change(function() {
        var stateId = $(this).val();
        if (stateId) {
            $.ajax({
                url: '{% url "load_cities" %}',
                data: {'state_id': stateId},
                dataType: 'json',
                success: function(data) {
                    $('#city-select').empty();
                    $('#city-select').append('<option value="">选择城市</option>');
                    $.each(data, function(index, city) {
                        $('#city-select').append('<option value="' + city.id + '">' + city.name + '</option>');
                    });
                }
            });
        } else {
            $('#city-select').empty();
            $('#city-select').append('<option value="">请先选择州</option>');
        }
    });
});
</script>
</body>
</html>

company_confirm_delete.html(删除确认页面)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>删除公司</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-4">
    <h2>确定要删除 "{{ company.company_name }}" 吗?</h2>
    <form method="post">
        {% csrf_token %}
        <button type="submit" class="btn btn-danger">确认删除</button>
        <a href="{% url 'company_list' %}" class="btn btn-secondary ml-2">取消</a>
    </form>
</div>
</body>
</html>

7. 初始化测试数据(可选)

创建company/fixtures/states_cities.json文件:

[
    {"model": "company.state", "pk": 1, "fields": {"name": "Karnataka"}},
    {"model": "company.city", "pk": 1, "fields": {"state": 1, "name": "Bangalore"}},
    {"model": "company.city", "pk": 2, "fields": {"state": 1, "name": "Mysore"}}
]

执行命令加载数据:

python manage.py loaddata states_cities.json

8. 运行项目

python manage.py runserver

访问http://localhost:8000即可使用完整的CRUD功能。

内容的提问来源于stack exchange,提问作者magib977

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 14:15:41