【问题标题】:Import csv data to web2py database and process uploads将 csv 数据导入 web2py 数据库并处理上传
【发布时间】:2014-10-15 17:50:23
【问题描述】:

我使用 web2py 制作了一个非常简单的单用户数据库应用程序,以部署到台式机上。我选择 web2py 的原因是它的简单性和非侵入式 Web 服务器。

我的问题是我需要从另一个应用程序迁移现有数据库,该应用程序刚刚预处理并准备成一个 csv 文件,现在可以完美地导入 web2py 的 sqlite 数据库。

现在,我在其中一个表中的“上传”字段存在问题,该字段对应于一个小图像,我已将该字段格式化为 de csv,并使用我创建的相应 .jpg 文件的名称从原始数据库中提取。问题是我没有管理如何将这些正确插入到上传文件夹中,因为 web2py 引擎会自动将用户上传的文件名更改为安全格式,并且将我的文件直接复制到文件夹中不起作用。

我的问题是,有人知道将此图像集包含到上传文件夹中的正确方法吗?我不知道是否有办法禁用此保护,或者我是否必须手动将其名称更改为有效的哈希值。我还考虑过将自动插入过程编码到数据库中的想法......

感谢大家的关注!

编辑(一个工作示例):

一个示例数据库:

db.define_table('product',
                Field('name'),
                Field('color'),
                Field('picture', 'upload'),
                )

然后使用我的应用程序中的默认 appadmin 模块,我导入了一个包含以下表单条目的 csv 文件:

product.name,product.color,product.picture
"p1","red","p1.jpg"
"p2","blue","p2.jpg"

然后在我的应用程序中我有通常的下载功能:

def download():
    return response.download(request, db)

我称之为请求上传到数据库的图像,例如,包含到视图中:

<img src="{{=URL('download', args=product.picture)}}" />

所以我的问题是我拥有与数据库记录相对应的所有图像,我需要将它们导入到我的应用程序中,方法是将它们正确包含到上传文件夹中。

【问题讨论】:

  • 任何具体的代码、输入、实际和预期的结果?
  • 更新了现有输入和预期结果的示例。谢谢。

标签: python web2py


【解决方案1】:

如果您希望通过标准 web2py 文件上传机制命名文件(出于安全原因,这是一个好主意)并通过内置的 response.download() 方法轻松下载,那么您可以执行以下操作。

在 /yourapp/controllers/default.py 中:

def copy_files():
    import os
    for row in db().select(db.product.id, db.product.picture):
        picture = open(os.path.join(request.folder, 'private', row.picture), 'rb')
        row.update_record(picture=db.product.picture.store(picture, row.picture))
    return 'Files copied'

然后将所有文件放在 /yourapp/private 目录中并转到 URL /default/copy_files (您只需要这样做一次)。这会将每个文件复制到 /uploads 目录并重命名,并将新名称存储在 db.product.picture 字段中。

注意,上面的函数不一定是控制器动作(虽然如果你这样做,你应该在完成后删除该函数)。相反,它可能是您通过 web2py 命令行运行的脚本(需要在应用程序环境中运行才能访问数据库连接和模型,以及对正确 /uploads 文件夹的引用)——在这种情况下,您需要在最后调用db.commit()(这在 HTTP 请求期间不是必需的)。

或者,您可以保持原样,而是 (a) 手动管理上传和下载,而不是依赖 web2py 的内置机制,或者 (b) 创建 custom_store 和 custom_retrieve 函数(不幸的是,我不对于picture 字段,'认为这些没有很好的记录),它将绕过 web2py 的内置存储和检索功能。不过,如果您只完成上述一次性流程,生活可能会更轻松。

【讨论】:

  • 谢谢你让我走上了正确的道路。一开始我遇到了一些问题,因为这种方法给了我以下错误: AttributeError: 'Row' object has no attribute 'update_record' 但是我将查询更改为:for row in db(db.product.id&gt;0).select(): 然后效果很好。我还在脚本末尾添加了db.commit(),因为更改没有正确显示。
  • 抱歉,我忘记在选择中包含id 字段(我已使用该修复更新了答案)——您不必选择所有字段。关于db.commit(),在我的示例中这不是必需的,但是您是正确的,将代码作为脚本运行时是必需的。
猜你喜欢
  • 1970-01-01
  • 2012-02-10
  • 1970-01-01
  • 2019-03-29
  • 2014-01-17
  • 1970-01-01
  • 2018-05-06
  • 2011-08-09
  • 1970-01-01
相关资源
最近更新 更多