我该在Flask SQLite数据库中使用什么数据类型来存储图像?

4

我有一个在Flask中的sqlite数据库中的db.model。它看起来像这样:

class Drink(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(64), index = True)
    kind = db.Column(db.String(64), index = True)
    image = db.Column(db.LargeBinary)

    def __init__(self, name, kind, image):
        self.name = name
        self.kind = kind
        self.image = image

    def __repr__(self):
        return '<Drink %r>' % self.name

那么,我的问题是我有这个列名为“image”的列,它将是一张实际的图片,但我不知道在Flask代码中使用什么数据类型。

以下是Flask代码:Flask

class DrinkAPI(Resource):
    def __init__(self):
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument('name', type = str, required = True, help = 'No name title provided', location = 'json')
        self.reqparse.add_argument('type', type = str, required = True, help='No type provided', location = 'json')
        self.reqparse.add_argument('image', type = blob, required = True, help='No image provided', location = 'json')
        super(DrinkAPI, self).__init__()

    def get(self, id):
        if checkDrink(id):
            info = getDrinkInfo(id)
            return {'id': id, 'name': info[0], 'type':info[1], 'image': info[2]}
        abort(404)

    def put(self, id):
        if checkDrink(id):
            args = self.reqparse.parse_args()
            deleteDrink(id)
            drink = Drink(args['name'], args['type'], args['image'])
            addDrink(drink)
            return {'drink' : marshal(drink, drink_fields)}, 201 
        abort(404)

    def delete(self, id):
        deleteDrink(id)
        return { 'result': True}

看到我将reqparse的类型设置为blob吗?这甚至不是一个实际的数据类型,但我不知道应该放什么。我需要子类化fields.Raw吗?有什么想法吗?谢谢。
问题的新方法 根据一些评论,似乎我应该将图像存储在我的静态文件夹中。我可以这样做。但是,如何引用它与我的数据库?它是对应于.jpg文件的字符串吗?

为什么不在数据库中存储图像文件的位置? - linbo
3
通常将图像/大型二进制数据存储在文件系统中是一个更好的主意。我不确定您特定的SQLite实现,但大多数这些框架都有简单的方法来上传/提供文件系统中的图像,并将键或路径存储在数据库中。如果您决定使用数据库,请尝试:https://dev59.com/h2gu5IYBdhLWcg3w3qt7 但要注意,这比使用文件系统和提供静态文件要低效得多。 - Jordan P
我想只在静态文件夹中放置图像也是可以的。那么,我只需要在数据库中有一个字符串,它是指向图片本身的路径吗?这是如何工作的?数据库如何知道它是路径而不仅仅是奇怪的字符串? - user2497586
2个回答

4

解析器添加参数('picture'),类型为werkzeug.datastructures.FileStorage,位置为'files'


+1并接受答案,因为它不需要使用HTML页面和上传按钮,只需API请求即可。 - user2497586

3

通常这样的图片需要从浏览器上传,除了被返回外。

因此我使用Flask-Uploads来处理所有存储和命名问题,无论是上传还是返回时。

以下是如何使用它的文档示例:

photos = UploadSet('photos', IMAGES)

@app.route('/upload', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST' and 'photo' in request.files:
        filename = photos.save(request.files['photo'])
        rec = Photo(filename=filename, user=g.user.id)
        rec.store()
        flash("Photo saved.")
        return redirect(url_for('show', id=rec.id))
    return render_template('upload.html')

@app.route('/photo/<id>')
def show(id):
    photo = Photo.load(id)
    if photo is None:
        abort(404)
    url = photos.url(photo.filename)
    return render_template('show.html', url=url, photo=photo)

您可以使用.save()方法将传入文件存储到目录中。Flask-Uploads会返回用于保存的文件名。稍后,您可以使用.url()或.path()来获取对保存文件的引用。

这难道不解决如何在数据库中表示它的问题吗? - user2497586
Flask-Uploads有一个.save()方法,它将获取上传的文件,将其存储在目录中,并返回一个文件名,您可以将其存储在数据库中。稍后,当您想要检索文件时,您可以使用.path()方法,将保存的文件名传递给它,它将返回完整的文件路径。 - David K. Hess
2
是的,这个答案实际上并没有告诉你如何将我们的图像存储在数据库中。关键是你根本不想这样做。你应该直接从文件系统中提供图像文件,事实上所有静态内容都应该这样做,最好通过你的“真正”的Web服务器(apache/nginx/任何其他)而不是通过Flask。 - Matthias Urlichs
@AlexChumbley 在问题标题没有改变的情况下修改了问题底部的内容。 - David K. Hess
超出规格,但请不要相信用户提供的文件名,并始终在存储它们之前对这些文件名进行哈希处理... 推荐阅读:http://flask.pocoo.org/docs/0.12/patterns/fileuploads/ - Leustad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接