内容描述
背景:
- 外键 “ForeignKey”可以对Django数据表进行“一对多”的表间约束
- 在对主表进行删除的时候,可以设置其对从表的约束操作
- 在对从表进行创建的时候,需要对从表的外键字段进行关联创建
定义一个函数,方便对主表和从表进行数据写入,用到的知识:
- 序列化器:ModelSerializer
- 外键:ForeignKey
- Python类知识
表格设计
主表记录实验概要信息,从表记录具体的实验对象、结果指标
不同的从表(实验对象)数据,都有其对应的主表(实验描述)数据
同一个主表(实验描述)数据,可以对应多个从表(实验对象)数据
主表
class Main_Sheet(models.Model):
# 模型名字
model_name = models.CharField(verbose_name='实验模型的名字', blank=False, max_length=255)
# 数据集有关
dataset_type_choices = (('SRU', 'SRU数据集'), ('PTA', 'PTA数据集'), ('HDPE', 'HDPE数据集'))
dataset_type = models.CharField(verbose_name='所用数据集类型', default='SRU', choices=dataset_type_choices, max_length=255)
# 实验记录
experiment_time = models.DateTimeField(verbose_name='实验时间', auto_now_add=True)
experiment_description = models.CharField(verbose_name='实验描述', blank=False, max_length=255)
def __str__(self) -> str:
return self.model_name + '-' + self.dataset_type
从表
class ELM_Sheet(models.Model):
# 关联字段
model_describ = models.ForeignKey(verbose_name='关联主表', to=Main_Sheet, on_delete=models.CASCADE)
# 评价指标
RMSE = models.FloatField(verbose_name='RMSE', default=0)
MSE = models.FloatField(verbose_name='MSE', default=0)
MAE = models.FloatField(verbose_name='MAE', default=0)
MRE = models.FloatField(verbose_name='MRE', default=0)
R2 = models.FloatField(verbose_name='R2', default=0)
函数设计
思路
-
初始化主从表写入类
-
主表内容写入
-
data:字典形式
-
serializer:序列化器
-
-
保存成功则返回该次创建主表数据的id信息,并设置为类属性,供从表创建使用
-
从表内容写入
- data:字典形式
- serializer:序列化器
- related_field:ForeignKey字段名称,字符串类型
- related_field_data_pk=None
- 若先前已经创建好了主表内容,则该字段传入主表内容id
- 若刚刚创建好主表内容,则该字段默认为None
代码实现
# 单例模式
class Singleton:
def __new__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
class Write_Data(Singleton):
def __init__(self) -> None:
self.__main_table_id = None
self.error_message = []
def write_main_sheet(self, data, serializer):
ser = serializer(data=data)
if ser.is_valid():
ser.save()
self.__main_table_id = ser.data.get('id')
print('已完成主表信息创建')
else:
self.error_message.append(ser.errors)
def write_sub_table(self, data, serializer, related_field, related_field_data_pk=None):
if related_field_data_pk == None:
data[related_field] = self.__main_table_id
else:
data[related_field] = related_field_data_pk
# 序列化器时候,有关外键的字段,传入pk即可
ser = serializer(data=data)
if ser.is_valid():
ser.save()
print('已完成该次副表信息创建')
return ser.data.get('id')
else:
self.error_message.append(ser.errors)
return None
注意点
通过序列化器创建外键关联的数据表内容时,ForeignKey传入主表对应数据的id即可,传入对应数据的模型类对象也行,都能通过序列化器验证