Python with peewee to MySQL,保存/更新双倍现有行

Posted

技术标签:

【中文标题】Python with peewee to MySQL,保存/更新双倍现有行【英文标题】:Python with peewee to MySQL, save / update doubles existing rows 【发布时间】:2014-10-21 15:07:24 【问题描述】:

我正在尝试从我的硬盘索引 ~150'000 jpg 和 cr2 照片文件,将它们写入 mysql DB,索引它们并最终创建一些 Intranet 页面来查看它们。

我想用 Python 编写索引器。我查看了 MySQLdb,但决定改用轻量级 ORM (PeeWee)。

作为 Python 的初学者(来自 php),到目前为止,我已经能够编写下面的代码。 它确实很好地索引文件并将它们放入 MySQL 中的表中。

我遇到的问题是,如果我再次运行代码,它只会添加/加倍表格中的行。我知道 PeeWee 在其“保存”算法中应该是“智能的”,并且应该自动更新现有的行而不是再次添加它们,但我无法让这种“智能”发挥作用。

(也许我误解了这个):http://peewee.readthedocs.org/en/latest/peewee/models.html

当您调用 save() 时,peewee 会根据主键值的存在来确定是执行 INSERT 还是执行 UPDATE

==> 我希望能得到一些支持/提示,了解我可以做些什么来更新代码,而不是仅仅添加行(更新与插入)

==> 另一个问题:PeeWee 能否处理具有约 150k 个实例的大对象?


SQL 表:

 +---------------------------------+
 |          table 'foto            | 
 +------------------+--------------+
 | column name      | type(len)    |         
 +------------------+--------------+
 | fid              | int(11)      |
 | file_name        | varchar(255) |
 | file_path        | text         |
 | file_fullpath    | text         |
 | date_changed     | datetime     |
 | size             | int(11)      |
 | file_extension   | varchar(5)   |
 | file_type        | varchar(255) |
 | file_mime        | varchar(255) |
 | last_indexed     | timestamp    |
 +------------------+--------------+

Python 代码:

<!-- language: python -->
    #!/usr/bin/python

    indexpath = './folder1/'

    import os
    from os.path import join, getsize
    import time, datetime
    import peewee
    from peewee import *
    import magic


    db = MySQLDatabase('fotolib', user="asdf", passwd="pass123")

    class Foto(peewee.Model):
        fid = PrimaryKeyField()
        file_name = CharField()
        file_path = TextField()
        file_fullpath = TextField()
        date_changed = DateTimeField()
        size = IntegerField()
        file_extension = CharField()
        file_type = CharField()
        file_mime = CharField()
        last_indexed = DateTimeField(default=datetime.datetime.now)

        class Meta:
            database = db

    for root, dirs, files in os.walk(indexpath):
        for name in files:
            foto = Foto(file_name=name,
                file_path=os.path.join(root, name),
                file_fullpath=os.path.abspath(os.path.join(root, name)),
                date_changed=datetime.datetime.strptime(time.ctime(os.path.getmtime(join(root, name))),
                                                        "%a %b %d %H:%M:%S %Y"),
                size=getsize(join(root, name)),
                file_extension=os.path.splitext(name)[1],
                file_type=magic.from_file(join(root, name)),
                file_mime=magic.from_file(join(root, name), mime=True)
            )
            foto.save()

【问题讨论】:

【参考方案1】:

Peewee 将根据您调用 save() 的对象上的 ID 更新或插入。它不会神奇地自省您的数据库。

获取或创建:http://docs.peewee-orm.com/en/latest/peewee/querying.html#get-or-create

【讨论】:

【参考方案2】:

我相信还不够优雅 - 但我想我找到了答案: 如果我首先在数据库中检查完整路径和文件是否已经存在并交出主键,那么 PeeWee 似乎能够执行 UPDATE 而不是 INSERT。 仍然困扰着我,我必须先再次查询数据库,然后必须将其放入如此不雅的 IF / ELSE 语句中,从而使我的代码行数加倍。

for root, dirs, files in os.walk(indexpath):
    for name in files:
        foto_exist_check = Foto.select(Foto.fid).where(Foto.file_fullpath == os.path.abspath(os.path.join(root, name)))
        if foto_exist_check.count() == 0:
            foto = Foto(
                file_name=name,
                file_path=os.path.join(root, name),
                file_fullpath=os.path.abspath(os.path.join(root, name)),
                date_changed=datetime.datetime.strptime(time.ctime(os.path.getmtime(join(root, name))),"%a %b %d %H:%M:%S %Y"),
                size=getsize(join(root, name)),
                file_extension=os.path.splitext(name)[1],
                file_type=magic.from_file(join(root, name)),
                file_mime=magic.from_file(join(root, name), mime=True)
            )
            foto.save()
        else:
            foto = Foto(
                fid = foto_exist_check.get().fid,
                file_name=name,
                file_path=os.path.join(root, name),
                file_fullpath=os.path.abspath(os.path.join(root, name)),
                date_changed=datetime.datetime.strptime(time.ctime(os.path.getmtime(join(root, name))),"%a %b %d %H:%M:%S %Y"),
                size=getsize(join(root, name)),
                file_extension=os.path.splitext(name)[1],
                file_type=magic.from_file(join(root, name)),
                file_mime=magic.from_file(join(root, name), mime=True)
            )
            foto.save()

【讨论】:

以上是关于Python with peewee to MySQL,保存/更新双倍现有行的主要内容,如果未能解决你的问题,请参考以下文章

Python:用 peewee 框架连接 SQL Server

peewee的使用 python orm

python peewee

让 peewee 在弹性豆茎上工作

如何更改 Flask-peewee 中的 UserDoesNotExist SELECT 行为 - python & mysql

python -- peewee处理数据库连接