Django中如何将存入数据库的JSON数据在模板中展示?
把JSON不良反应数据存入Django数据库并在模板展示的方案
我来帮你搞定这个需求,下面分两种实用方案,你可以根据自己的业务场景选择:
方案一:用JSONField直接存储整个反应数组(快速简单)
如果你的数据不需要单独查询、过滤某个不良反应项,这个方案最省事,直接把整个reaction数组存成JSON格式。
1. 定义数据库模型
在你的models.py里创建模型:
from django.db import models class MedicationReaction(models.Model): # 可以添加其他关联字段,比如药品名称、批次号等 reactions = models.JSONField() # Django 3.1+支持通用JSONField,老版本用PostgreSQL专属的JSONField created_at = models.DateTimeField(auto_now_add=True)
2. 解析JSON并存入数据库
拿到你的JSON数据后,解析成Python字典,再创建模型实例:
import json # 你的原始JSON数据 json_str = '{"reaction": [{"reactionmeddrapt": "Stress fracture", "reactionmeddraversionpt": "20.1", "reactionoutcome": "1"}, {"reactionmeddrapt": "Drug effect incomplete", "reactionmeddraversionpt": "20.1", "reactionoutcome": "6"}, {"reactionmeddrapt": "Osteoarthritis", "reactionmeddraversionpt": "20.1", "reactionoutcome": "3"}, {"reactionmeddrapt": "Fracture delayed union", "reactionmeddraversionpt": "20.1", "reactionoutcome": "..."}]}' # 解析JSON data = json.loads(json_str) # 存入数据库 MedicationReaction.objects.create(reactions=data['reaction'])
3. 编写视图传递数据到模板
在views.py里写视图函数:
from django.shortcuts import render from .models import MedicationReaction def reaction_display(request): # 获取所有存储的反应数据 reaction_records = MedicationReaction.objects.all() return render(request, 'reaction_display.html', {'records': reaction_records})
4. 在模板中渲染数据
创建templates/reaction_display.html,遍历数据展示:
<h1>药物不良反应记录</h1> {% for record in records %} <div class="record-card"> <h3>记录创建时间:{{ record.created_at|date:"Y-m-d H:i" }}</h3> <ul> {% for reaction in record.reactions %} <li> <p><strong>症状名称:</strong>{{ reaction.reactionmeddrapt }}</p> <p><strong>MedDRA版本:</strong>{{ reaction.reactionmeddraversionpt }}</p> <p><strong>反应结果:</strong>{{ reaction.reactionoutcome }}</p> <hr> </li> {% endfor %} </ul> </div> {% endfor %}
方案二:用关联模型存储单个反应项(适合复杂查询)
如果需要单独查询某个症状、过滤特定结果的反应,这个方案更符合关系型数据库的设计,把每个reaction拆成独立的表记录。
1. 定义关联模型
在models.py里创建主模型和关联的反应模型:
from django.db import models class Medication(models.Model): # 主模型,存储药品基础信息(按需添加字段) name = models.CharField(max_length=255, verbose_name="药品名称") created_at = models.DateTimeField(auto_now_add=True) class AdverseReaction(models.Model): # 关联到药品主模型 medication = models.ForeignKey(Medication, on_delete=models.CASCADE, related_name='adverse_reactions') symptom = models.CharField(max_length=255, db_column='reactionmeddrapt', verbose_name="不良反应症状") meddra_version = models.CharField(max_length=50, db_column='reactionmeddraversionpt', verbose_name="MedDRA版本") outcome = models.CharField(max_length=10, db_column='reactionoutcome', verbose_name="反应结果") # 可以给结果值加友好显示 OUTCOME_MAP = { '1': '治愈', '3': '好转', '6': '未知', # 补充其他对应的结果描述 } @property def outcome_display(self): return self.OUTCOME_MAP.get(self.outcome, self.outcome)
2. 批量存入数据
解析JSON后,批量创建关联记录:
import json json_str = '{"reaction": [{"reactionmeddrapt": "Stress fracture", "reactionmeddraversionpt": "20.1", "reactionoutcome": "1"}, {"reactionmeddrapt": "Drug effect incomplete", "reactionmeddraversionpt": "20.1", "reactionoutcome": "6"}, {"reactionmeddrapt": "Osteoarthritis", "reactionmeddraversionpt": "20.1", "reactionoutcome": "3"}, {"reactionmeddrapt": "Fracture delayed union", "reactionmeddraversionpt": "20.1", "reactionoutcome": "..."}]}' data = json.loads(json_str) # 先创建药品主记录(这里假设药品名称可以自定义) medication = Medication.objects.create(name="某药品") # 批量构建反应对象,提升效率 reaction_objects = [] for item in data['reaction']: reaction_objects.append(AdverseReaction( medication=medication, symptom=item['reactionmeddrapt'], meddra_version=item['reactionmeddraversionpt'], outcome=item['reactionoutcome'] )) # 批量插入数据库 AdverseReaction.objects.bulk_create(reaction_objects)
3. 编写视图(预取关联数据避免N+1查询)
在views.py里:
from django.shortcuts import render from .models import Medication def reaction_detail(request): # 预取关联的不良反应数据,减少数据库查询次数 medications = Medication.objects.prefetch_related('adverse_reactions').all() return render(request, 'reaction_detail.html', {'medications': medications})
4. 模板渲染(显示友好的结果描述)
创建templates/reaction_detail.html:
<h1>药品不良反应明细</h1> {% for med in medications %} <div class="medication-section"> <h2>{{ med.name }}</h2> <p>记录创建时间:{{ med.created_at|date:"Y-m-d H:i" }}</p> <ul> {% for reaction in med.adverse_reactions.all %} <li> <p><strong>症状:</strong>{{ reaction.symptom }}</p> <p><strong>MedDRA版本:</strong>{{ reaction.meddra_version }}</p> <p><strong>反应结果:</strong>{{ reaction.outcome_display }}</p> <hr> </li> {% endfor %} </ul> </div> {% endfor %}
一些额外提示
- 如果用方案一的JSONField,Django 3.1以下版本需要使用
django.contrib.postgres.fields.JSONField,且仅支持PostgreSQL数据库;3.1+版本的通用JSONField支持更多数据库。 - 方案二中的
outcome字段如果是纯数字,可以改成IntegerField,更符合数据库类型规范。 - 模板里可以添加CSS样式让展示更美观,比如给卡片、列表加边框和间距。
内容的提问来源于stack exchange,提问作者Sapna Sharma
相关产品推荐
相关产品推荐

