使用 Peewee 在 Postgres 中记录重复内容

问题描述 投票:0回答:1

我已将权限交给一个空白的 postgres 实例,并负责设计和实现我们的小型应用程序的后端。该应用程序允许客户搜索设备并根据这些设备的扫描在它们之间建立关联。

先总结一下:
我有多个表在一对多设置中引用另一个表中的条目;当我将数据提取到任何反向引用该表的表中时,我不小心创建了该记录的副本。

详情:
我已经像这样设置了数据库:

桌子 包含
设备 物理+逻辑地址信息、名称等
留言 设备发送/接收的流量
文件 已安装的应用程序+访问信息
用户账户 用户访问日志

我的目标是在每个设备的设备表中都有一个条目,然后在其他每个表(消息、文件、用户帐户)中都有一个外键字段来引用它们所属的设备。

在 peewee 中我将其实现为:

class Device(BaseModel):
    id = AutoKey()
    md5 = FixedCharField(32) # hash of the file the device comes from
    #... other attrs


class Message(BaseModel):
    id = AutoKey()
    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)

我尝试了各种与小便物体相关的事情

.save()
,并将其放在其他位置,但一切都是徒劳。

我希望这很简单!感谢您提供的任何帮助!

python postgresql peewee
1个回答
0
投票

问题可能是您的自定义

AutoKey
或其他原因,因此 peewee 正在发出 INSERT。您应该通过将 DEBUG 处理程序添加到 peewee 日志命名空间来记录您的查询。或者,您可以在执行获取或创建操作时查看代码的哪个分支正在执行。或者您可以在文件哈希上添加 UNIQUE 约束。您可以做很多事情来解决这个问题,所以去获取更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.