【问题标题】:Flask - How can I query a BLOB image data and display it on HTML / Jinja2?Flask - 如何查询 BLOB 图像数据并将其显示在 HTML / Jinja2 上?
【发布时间】:2020-07-29 18:11:52
【问题描述】:

所以,我有一个表单,用户可以在其中发布标题、正文并上传图片。我从表单中取出该图像并将其作为“Blob”保存到我的 Postgres 数据库中。

但是我有一个问题,我对如何查询该图像 blob 数据并解码并将其显示给用户感到困惑。

这些是我的桌子:

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(120), unique=True, nullable=False)
    username = db.Column(db.String(30), unique=True, nullable=False)
    password = db.Column(db.String(120), nullable=False)
    date_joined = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    posts = db.relationship('Post', backref='author', lazy=True, passive_deletes=True)


class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    body = db.Column(db.Text, nullable=False)
    link = db.Column(db.LargeBinary)
    date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    user_id = db.Column(db.Integer, db.ForeignKey( 'user.id', ondelete='CASCADE'), nullable=False)

这是将 POST 和 IMAGE 保存到我的数据库和静态文件夹目录的路径:

@app.route('/create/post', methods=['GET', 'POST'])
def create_post():
    # Image upload and validation
    if request.method == 'POST':
        if request.files:

            if allowed_image_size(request.cookies.get('filesize')):
                flash('Image exceeds the maximum size limit of 5 MB!', 'danger')
                return redirect(request.url)

            image = request.files['uploadImg']

            if image.filename == '':
                flash('No image detected or file name is empty!', 'danger')
                return redirect(request.url)

            if not allowed_images(image.filename):
                flash('Invalid image extension!', 'danger')
                return redirect(request.url)
            else:
                filename = secure_filename(image.filename)
                image.save(os.path.join(app.config['IMAGE_UPLOADS'], image.filename))

    # Regular Posts
    form = PostForm()
    if form.validate_on_submit():
        post = Post(title=form.title.data,
                    body=form.body.data, link=image.read(), user_id=current_user.id)
        db.session.add(post)
        db.session.commit()
        flash('Post submitted', 'success')
        return redirect(url_for('home'))
    return render_template('create_post.html', title='Create Post', form=form)

另外,当我查询帖子以查看是否可以检索数据时,使用类似posts = Post.query.all() 和使用print(posts.link.read())。我收到一条错误消息,提示 AttributeError: 'list' object has no attribute 'link'

@app.route('/')
@app.route('/home')
def home():
    posts = Post.query.all()
    print(posts.link.read())
    return render_template('home.html', title='Home', posts=posts)

【问题讨论】:

  • 我相信最好将图像路径而不是 blob 存储到数据库中。然后,您可以将该图像路径传递给 render_template 调用。我对烧瓶有点模糊,因为我有一段时间没有使用它了,但这样做很容易。
  • 啊是的,我的静态目录中确实保存了图像,但问题是,我不知道如何将图像显示给发布它的用户。因此,用户 #1 创建了两个带有图像的帖子,我不知道如何在不使用数据库的情况下将这两个图像连接到用户 #1。
  • posts 表中是否有图像 blob?你什么时候把它存储为 blob 的?我之前的做法是将图像的路径存储在帖子表中。然后,当您将 POST 对象传递到模板中时,您可以执行类似 的操作

标签: python python-3.x postgresql flask flask-sqlalchemy


【解决方案1】:

我认为您应该将图像作为路径名存储到您的帖子表中,而不是 blob。

在您的数据库中将其更改为:

 link = db.Column(db.String(30))

然后在将post添加到数据库时,将图像文件名路径的字符串传递到Post中

使用随机字符串重命名文件也是一种很好的做法,因为许多用户可能会上传myCatPicture.jpg,这会导致它覆盖文件。

这样就可以了

def get_random_string(length):
    # Random string with the combination of lower and upper case
    letters = string.ascii_letters
    return ''.join(random.choice(letters) for i in range(length))

然后在保存图片的时候保存新的文件名

    if not allowed_images(image.filename):
        flash('Invalid image extension!', 'danger')
        return redirect(request.url)
    else:
        ext = os.path.splitext(file_name)[1]  # get the file extension
        new_filename = get_random_string(20)  # create a random string

        image.save(os.path.join(app.config['IMAGE_UPLOADS'], new_filename+ext))  # save with the new path

并在帖子创建中使用新字符串。

post = Post(title=form.title.data,
                    body=form.body.data, link=os.path.join(app.config['IMAGE_UPLOADS'], new_filename+ext) , user_id=current_user.id)   #here we are substituting the old blod with the new stored image path string

注意:

只要您将路径存储在数据库中,文件名就无关紧要。您可以随时查找以获取图像/路径。

...

然后在你的模板中(因为你已经有了所有的帖子)你可以开始一个 for 循环

{% for post in range(len(posts)) %}
    <h1> {{ post.title }} </h1>
    <img src= {{post.link }} >
    <p> {{ post.body }} </p>
{% endfor %}

这应该遍历每个帖子标题、图像和内容等。

我再次对此有点模糊。但认为这几乎涵盖了它。

【讨论】:

猜你喜欢
  • 2016-06-05
  • 2021-12-06
  • 1970-01-01
  • 2015-05-28
  • 2019-10-01
  • 1970-01-01
  • 2014-06-15
  • 2013-12-24
  • 2014-08-30
相关资源
最近更新 更多