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

Django Admin自定义表单:创建Region时批量导入城市Excel

实现Django Admin创建Region(Canton)时批量导入关联City的功能

1. 安装Excel处理依赖

首先安装用于解析Excel的依赖包:

pip install openpyxl

2. 确认模型结构(参考)

假设你的模型定义大致如下(可根据实际代码调整字段):

# models.py
from django.db import models

class Canton(models.Model):
    name = models.CharField(max_length=100, verbose_name="区域名称")
    # 其他自定义字段...

    def __str__(self):
        return self.name

class City(models.Model):
    name = models.CharField(max_length=100, verbose_name="城市名称")
    canton = models.ForeignKey(Canton, on_delete=models.CASCADE, related_name="cities", verbose_name="所属区域")
    # 其他自定义字段...

    def __str__(self):
        return self.name

3. 自定义Admin表单

创建包含Excel上传字段的自定义表单,并添加文件格式验证:

# admin.py
from django import forms
from .models import Canton

class CantonAdminForm(forms.ModelForm):
    excel_file = forms.FileField(
        label="批量导入城市Excel",
        required=False,
        help_text="上传包含城市名称的Excel文件,第一行为表头(如'城市名称')"
    )

    class Meta:
        model = Canton
        fields = "__all__"

    def clean_excel_file(self):
        file = self.cleaned_data.get("excel_file")
        if file:
            if not file.name.endswith((".xls", ".xlsx")):
                raise forms.ValidationError("仅支持上传Excel格式文件(.xls/.xlsx)")
        return file

4. 重写CantonAdmin的保存逻辑

关联自定义表单,并重写save_model方法完成Excel解析与City批量创建:

# admin.py
from django.contrib import admin
from openpyxl import load_workbook
from .models import Canton, City

@admin.register(Canton)
class CantonAdmin(admin.ModelAdmin):
    form = CantonAdminForm
    # 配置新增页面的字段布局
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('name', 'excel_file',)  # 替换为你的实际字段
        }),
    )

    def save_model(self, request, obj, form, change):
        # 先保存Canton对象
        super().save_model(request, obj, form, change)
        
        # 仅在新增操作时处理Excel导入
        excel_file = form.cleaned_data.get("excel_file")
        if excel_file and not change:
            try:
                wb = load_workbook(excel_file)
                sheet = wb.active
                # 跳过表头,从第二行开始读取数据
                for row in sheet.iter_rows(min_row=2, values_only=True):
                    city_name = row[0]
                    if city_name:
                        # 避免重复创建相同城市
                        City.objects.get_or_create(
                            name=city_name.strip(),
                            canton=obj
                        )
            except Exception as e:
                raise forms.ValidationError(f"Excel解析失败:{str(e)}")

5. 注意事项

  • 确保Excel文件格式合规:第一行是表头,后续行是城市名称数据
  • 若City模型有其他必填字段,需在解析时补充对应数据
  • 可根据需求调整add_fieldsets,让上传字段在Admin页面合理展示
  • 如果需要支持编辑Region时重新导入城市,可移除not change的判断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 05:03:20