Django执行makemigrations时如何仅创建模型并插入一次初始数据
问题根因
你当前的问题根源是:将数据插入的循环逻辑直接写在了models.py的顶层作用域,Django在执行任何命令(包括makemigrations、migrate、runserver等)时都会先加载模型文件,这段代码就会被触发执行,所以每次运行都会重复插入数据。
推荐解决方案:使用Django自定义迁移实现单次初始化
这个方案完全符合Django的设计规范,迁移文件只会被执行一次,不会出现重复插入的问题,步骤如下:
- 先删除你现在写在
models.py里的countries字典和后续的插入循环代码,避免每次加载模型都触发插入。可以给abbr字段加上唯一约束,从数据库层面避免重复数据:
from django.db import models class Country(models.Model): cid = models.SmallAutoField(primary_key=True) label = models.CharField(max_length=100) # 加unique约束,从底层避免重复的国家缩写 abbr = models.CharField(max_length=3, unique=True)
- 运行命令生成创建Country表的基础迁移文件:
python manage.py makemigrations <你的App名称>
- 运行命令生成一个空的迁移文件,用于写入初始化数据的逻辑:
python manage.py makemigrations <你的App名称> --empty
- 打开生成的空迁移文件(路径一般为
<你的App名称>/migrations/0002_xxx.py),修改内容如下:
from django.db import migrations def init_country_data(apps, schema_editor): # 注意这里不能直接import你的Country模型,要用apps.get_model获取当前版本的模型 Country = apps.get_model('<你的App名称>', 'Country') countries = { "AFG": "Afghanistan", "ALB": "Albania", "DZA": "Algeria", "ASM": "American Samoa", "AND": "Andorra", "AGO": "Angola", "AIA": "Anguilla" } for abbr, label in countries.items(): # 只有缩写不存在时才创建数据,双重保险避免重复 Country.objects.get_or_create(abbr=abbr, defaults={"label": label}) class Migration(migrations.Migration): # 依赖前面创建表的迁移文件,这里自动生成的不用改 dependencies = [ ('<你的App名称>', '0001_initial'), ] operations = [ migrations.RunPython(init_country_data) ]
- 最后执行迁移命令即可,后续不管运行多少次
makemigrations,只要不手动修改这个迁移文件,初始化逻辑只会执行一次:
python manage.py migrate
备选方案:使用fixture加载
如果不需要把初始化逻辑和迁移绑定,也可以用Django的fixture功能:
- 在你的App下新建
fixtures目录,创建countries.json文件写入初始化数据 - 手动执行一次
python manage.py loaddata countries.json即可完成数据插入,不会重复执行。
内容的提问来源于stack exchange,提问作者asprin
相关产品推荐
相关产品推荐

