python-3.x - IntegrityError Django ORM
问题描述
我正在处理一个包含咨询和医疗数据的文件。我还在处理另一个只包含考试数据的文件。
作为一种好的做法,我将模型归一化,如下所示:
class Medico(models.Model):
codigo_medico = models.IntegerField(primary_key=True, unique=True)
nome = models.CharField(max_length=50)
class Consulta(models.Model):
numero_guia = models.IntegerField(primary_key=True)
data_consulta = models.DateField()
valor_consulta = models.FloatField()
codigo_medico = models.ForeignKey(Medico, on_delete=models.CASCADE)
class META:
ordering = ['data_consulta']
class Exame(models.Model):
exame = models.CharField(max_length=30, null=False)
valor_exame = models.FloatField()
numero_guia_consulta = models.ForeignKey(Consulta, on_delete=models.CASCADE)
class META:
ordering = ['-valor_exame']
请注意,医疗模型的ID字段标记为unique = true,因为无论咨询如何,都只能有一个具有特定代码的医生。
我做了文件处理,效果很好。当试图运行同一个文件时,知道医生的数据是唯一的,我得到 IntegrationError (return Database.Cursor.execute (self, query, params) django.db.utils.IntegrityError: UNIQUE constraint failed: relatorio_medico.codigo_medico) 这个预料之中。我精确地进行了这个处理以获得重复的数据。问题是,如果某个特定的咨询文件到了,我的基地总会有一个已经注册的医生,所以我需要处理 IntegratedError 案例。
我尝试使用 try 和 except 但无济于事。
我是如何实现的:
from relatorio.models import Exam, Consultation, Doctor
from django.db import IntegrityError as IE
from sqlite3 import IntegrityError
class CreateDataExams:
"""
Cria os dados no banco de dados a partir de um lote de dados de exames.
"""
def __init__(self, data_exams):
self.data_exams = data_exams
def create_exams(self):
exams = []
for item in self.data_exams[1:]:
new_item = item.split(';')
obj_exams = Exame(numero_guia_consulta=new_item[0], exame=new_item[1], valor_exame=new_item[2])
exams.append(obj_exams)
Exame.objects.bulk_create(exams)
class CreateDataAppointment:
"""
Cria os dados no banco de dados a partir de um lote de dados de consulta.
"""
def __init__(self, data_appointment):
self.data_appointment = data_appointment
def create_appointment(self):
appointment = []
medico = []
del self.data_appointment[-1]
for item in self.data_appointment[1:]:
new_item = item.split(';')
obj_medico = Medico(codigo_medico=new_item[1], nome=new_item[2])
medico.append(obj_medico)
Medico.objects.bulk_create(medico, batch_size=1000)
for item in self.data_appointment[1:]:
new_item = item.split(';')
obj_appointment = Consulta(numero_guia=int(new_item[0]), data_consulta=new_item[3],
valor_consulta=new_item[4],
codigo_medico=Medico.objects.get(codigo_medico=int(new_item[1])))
appointment.append(obj_appointment)
Consulta.objects.bulk_create(appointment)
下面是我正在处理的数据模型。考试:
预约:
请注意,某些医生的代码是重复的。
我的问题是:保存医生数据时如何处理这种情况,考虑到我正在批量处理,由于文件的大小超过 20k 记录?
我试着用
from django.db import IntegrityError
try:
Medico.objects.bulk_create(medico, batch_size=1000)
except IntegrityError:
Medico.objects.bulk_update(medico, ['nome'], batch_size=1000)
但没有成功。发生同样的错误。错误:
解决方案
如果它们不存在,最简单的选择是一个一个地创建它们:
obj, created = Medico.objects.get_or_create(codigo_medico=new_item[1], nome=new_item[2])
如果您的对象已经存在,则将从数据库中获取,否则将插入数据库。
您还使用了另一个我认为是名称的字段,因此寻找具有相同 id 和相同字符串的行很慢,因为您的nome
字段没有被索引,除了它是一个额外的查找之外。因此,您可以删除名称并只使用查找速度非常快的 id。
exists = Medico.objects.filter(codigo_medico=new_item[1]).exists()
# only create a new object for bulk create if it doesn't exists
if not exists:
obj_medico = Medico(codigo_medico=new_item[1], nome=new_item[2])
medico.append(obj_medico)
为了使其更加优化,您可以获取所有 id 并仅在 id 不在该列表中时创建一个对象:
doctor_ids = list(Medico.objects.all().values_list('id', flat=True))
for item in self.data_appointment[1:]:
new_item = item.split(';')
if new_item[1] not in doctor_ids:
obj_medico = Medico(codigo_medico=new_item[1], nome=new_item[2])
medico.append(obj_medico)
推荐阅读
- assembly - 嵌入式系统:使用汇编语言时的内存布局
- visual-studio-code - ExecutionPolicy 未定义 - Python 和 Visual Studio 代码
- node.js - 如何在 Kubernetes 中使用 NGINX 运行 Express
- javascript - TypeError:无法读取未定义表的属性“0”
- javascript - 我需要在 javascript 中运行一些 C++ 代码
- php - 如何抓取和组合多个 application/ld+json 标签?
- ruby-on-rails - Redis 没有连接到 channel.js
- mysql - mysql:在这种情况下是否需要 mysql_real_connect?
- python - 在 Python 中运行 nuclei 错误。它应该可以工作,但由于某种原因出错了
- javascript - 从存储中获取产品并比较数量