我被交给了一个空白的postgres示例,并被赋予了设计和实现我们小应用程序后端的任务。该应用程序允许客户搜索设备,并根据对这些设备的扫描在它们之间建立关联。
首先汇总:
我有多个表在一对多设置中引用另一个表中的条目;当我将数据摄取到反向引用该表的任何表中时,我意外地创建了该记录的副本。
详情:
我把数据库设置成这样:
| 表|包含|
| --|--|
| 设备|物理+逻辑地址信息、名称等。|
| 消息|设备发送/接收的流量|
| 文件|已安装的应用程序+访问信息|
| 用户帐户|用户访问日志|
我的目标是在设备表中为每个设备创建一个条目,然后在其他每个表(消息、文件、用户帐户)中创建一个外键字段,以引用它们所属的设备。
在peewee中,我将其实现为:
class Device(BaseModel):
id = AutoField()
md5 = FixedCharField(32) # hash of the file the device comes from
#... other attrs
class Message(BaseModel):
id = AutoField()
dev_ref = ForeignKey(Device, backref="messages")
#... other attrs
字符串
目前,我们所有的设备扫描数据都是以Excel电子表格的形式提供给我们的,每个表格中的条目都有多个相关的工作表。
def sheet_to_model(
source_file: str,
sheet: str,
model: peewee.Model):
df = pd.read_excel(source_file, sheet_name=sheet)
file_hash = md5(open(source_file,'rb').read()).hexdigest()
# try to get an existing device, otherwise make a new one
# **probably the crux of the problem**
try:
device = Device.select().where(Device.md5 == file_hash).get()
except:
device = Device(md5 = file_hash, ...) #
device.save()
# iterate over rows, translate them to db col names, etc.
for row in df.iterrows():
...
attrs = { 'column' : 'data from spreadsheet' }
# also maybe the problem here?
entry = model.create(dev_ref = device.id, **attrs)
entry.save()
型
然后我像这样摄取数据库:
# map of sheet name to the peewee model it corresponds to
sheet_model = {
"Messages" : Message,
"Files" : File,
"User Accounts": UserAccounts
}
# go file by file and ingest sheet by sheet
for file in glob.glob("file/location/whatever"):
xl_file = openpyxl.load_workbook(file, read_only=True)
for sheet in filter(lambda k: k in sheet_model, xl_file.sheetnames):
sheet_to_model(file, sheet, sheet_model[sheet])
型
我在“消息”、“文件”和“用户帐户”中的所有条目都很好地进入了它们各自的表,但对于我从电子表格中摄取的每个新工作表,它都会在“设备”表中创建一个重复的行。也就是说,如果我摄取了设备1的Excel文件,其中包含用于消息、文件和用户帐户的工作表,那么我的“设备”表中现在将有3行称为“设备1”。我在这里做错了什么?
问题是出在我的代码中,还是出在外键的底层设计中?
我已经两次和三次检查了查找,看看设备是否存在,即如果我在设备表中有一个设备,它是完全正确的:
dev = Device.select().where(Device.md5 == file_hash).get()
dev.id # 1
dev.md5 # 123456789abcdef123456789abcdef (or whatever)
型
我尝试了各种与peewee对象.save()
相关的东西,并将其放在其他位置,但都是徒劳的。
我希望这是简单的东西!谢谢你的任何帮助,你可以提供!
1条答案
按热度按时间v9tzhpje1#
问题可能是你的自定义
AutoKey
或其他什么,所以peewee发出了错误消息。你应该通过向peewee日志命名空间添加一个DEBUG处理程序来记录你的查询。或者你可以看到当你执行get-or-create时,你的代码的哪个分支正在执行。或者你可以在文件哈希上添加一个UNIQUE约束。你可以做很多事情来解决这个问题,所以去获取更多信息。