如何将字典列表中的数据保存到Django的Pokemon模型中
实现步骤
1. 模型修正(必做)
你当前定义的Pokemon模型中evolution字段为IntegerField类型,但原始数据中evolution存储的是进化后的宝可梦名称字符串,无法直接存入,有两种修正方案:
- 方案1:直接存储进化后的宝可梦名称,修改字段为:
evolution = models.CharField(max_length=255, null=True, blank=True)
- 方案2:存储进化后宝可梦的id(更符合数据库设计规范),修改为自关联外键:
evolution = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, related_name='pre_evolution')
修改完成后执行python manage.py makemigrations和python manage.py migrate更新数据库结构。
2. 数据处理与存储
方案A:直接用Django ORM批量写入(适合脚本/初始化场景)
代码示例,直接在Django shell或者自定义管理命令中运行:
# 你的原始数据 pokemon_data = [ {'evolution': 'charizard', 'height': 11, 'id_pokemon': '5', 'name': 'charmeleon', 'stats': [[80, 'speed'], [65, 'special-defense'], [80, 'special-attack'], [58, 'defense'], [64, 'attack'], [58, 'hp']], 'weight': 190}, {'evolution': 'charmeleon', 'height': 6, 'id_pokemon': '4', 'name': 'charmander', 'stats': [[65, 'speed'], [50, 'special-defense'], [60, 'special-attack'], [43, 'defense'], [52, 'attack'], [39, 'hp']], 'weight': 85}, {'evolution': 'None', 'height': 17, 'id_pokemon': '6', 'name': 'charizard', 'stats': [[100, 'speed'], [85, 'special-defense'], [109, 'special-attack'], [78, 'defense'], [84, 'attack'], [78, 'hp']], 'weight': 905} ] # 预生成宝可梦名称到ID的映射(仅方案2需要) name_to_id = {item['name']: int(item['id_pokemon']) for item in pokemon_data} instance_list = [] for item in pokemon_data: # 转换stats为字段对应字典 stats = {stat[1].replace('-', '_'): stat[0] for stat in item['stats']} # 处理evolution字段 if item['evolution'] == 'None': evolution_val = None else: # 方案1:直接用原始值 # evolution_val = item['evolution'] # 方案2:转换为对应id evolution_val = name_to_id[item['evolution']] # 构造实例 instance_list.append(Pokemon( id_pokemon = int(item['id_pokemon']), name = item['name'], weight = item['weight'], height = item['height'], special_defense = stats['special_defense'], special_attack = stats['special_attack'], defense = stats['defense'], attack = stats['attack'], hp = stats['hp'], speed = stats['speed'], evolution = evolution_val )) # 批量写入数据库,ignore_conflicts=True避免主键重复报错 Pokemon.objects.bulk_create(instance_list, ignore_conflicts=True)
方案B:配合Django REST Framework序列化器写入(适合接口接收数据场景)
先定义序列化器:
from rest_framework import serializers from .models import Pokemon class PokemonSerializer(serializers.ModelSerializer): class Meta: model = Pokemon fields = '__all__'
数据处理逻辑:
# 先按方案A的逻辑预处理数据,把stats展开、evolution、id_pokemon转成对应格式,得到processed_data列表 serializer = PokemonSerializer(data=processed_data, many=True) if serializer.is_valid(raise_exception=True): serializer.save()
注意事项
- 如果需要更新已存在的宝可梦数据,可将
bulk_create替换为bulk_update,指定更新字段即可 - 批量插入的执行效率远高于循环单条save,数据量较大时推荐使用
- 序列化器会自动做字段类型校验,出现报错可通过
serializer.errors定位问题
内容的提问来源于stack exchange,提问作者Perse
相关产品推荐
相关产品推荐

