使用Flask的wtf表单数据保存的问题

最近学习使用flask编写网站,遇到问题为使用Flask_wtf做一个产品提交的表单,环境是python+flask+wtfrom+MySql,表单里面包含有产品图片,所以在保存到MYsql数据库中遇到问题,网上查了一些资料,都是要不单文字传输,要不就是单文件上传,没有这种既有文字又有图片的,自测也是单文字和单图片都可以解决。本人学习python时间不长,希望大家多多指点。

需要解决的问题的为,1、 从前端传过来的图片为<FileStorage: '1.png' ('image/png')>,文件保存时通过格式处理保存为/uploads/products/1.png,但提交到数据库保存的还是<FileStorage: '1.png' ('image/png')>,如何进行转换也保存为/uploads/products/1.png?
2、如果数据库保存的是<FileStorage: '1.png' ('image/png')>,前台在浏览时如何调用?
from.py

class ProductForm(FlaskForm):
    name = wtforms.StringField('产品名称',validators=[Length(min=2,max=30,message='产品名称的字符数量在2-30之间')])
    pro_No = wtforms.StringField('产品型号',validators=[Length(min=2,max=30,message='产品型号的字符数量在2-30之间')])
    pic = wtforms.FileField('产品图片',validators=[FileRequired(),
        FileAllowed(["png","jpg","gif","jpeg"], "仅支持PNG,jpg,gif,jpeg格式图片上传")  #**图片**
    ])
    title = wtforms.StringField('简介',validators=[Length(max=30,message='产品简介的字符数量不能大于30')])
    body = wtforms.StringField('产品详情',validators=[Length(max=500,message='产品名称的字符数量不能大于500')])
    type_id = wtforms.SelectField('产品类型')

views.py

   def post(self,id=None):
        form = ProductForm(request.form)
        pro = product() if not id else  db.session.query(product).get(id)
        if form.validate_on_submit():
            pic = form.pic.data
            picname = form.pic.data.filename
            filepath = os.path.dirname(os.path.abspath(__file__))
            savepath = os.path.join(filepath, '/uploads/products')
            pic.save(os.path.join(savepath, picname))
            form.populate_obj(pro)
        if not id:
            db.session.add()
        db.session.commit()
        return redirect(url_for('products.product_create'))

html

{% extends 'admin/layout.html' %}
{% block page_head %}

        <div class="col-lg-10">
            <section class="panel">
                <header class="panel-heading">
                    Basic Forms
                </header>
                <div class="panel-body">
                    <form role="form" method='POST'  enctype="multipart/form-data">
                        {{ form.csrf_token }}
                        <div class="form-group">
                            {{ form.name.label }}
                            {{ form.name (class="form-control") }}
                        </div>
                        <div class="form-group">
                            {{ form.pro_No.label }}
                            {{ form.pro_No (class="form-control") }}
                        </div>
                              <div class="form-group">
                            {{ form.type_id.label }}
                            {{ form.type_id (class="form-control") }}
                        </div>
                        <div class="form-group">
                            {{ form.pic.label }}
                             {{ form.pic  (class="form-control")}}
                        </div>
                        <div class="form-group">
                            {{ form.title.label }}
                            {{ form.title (class="form-control") }}
                        </div>
                        <div class="form-group">
                            {{ form.body.label }}
                            {{ form.body (class="form-control") }}
                        </div>

                        <button type="submit" class="btn btn-info">提交</button>
                    </form>

                </div>
            </section>
        </div>

{% endblock %}


【以下回答由 GPT 生成】

问题1: 如何将用户上传的图片保存到数据库中?

解决方案: 1. 在数据库中添加一个名为"image"的列,用于保存图片的二进制数据。

  1. 在表单中将图片字段改为"FileField"类型,并且添加"Wtforms FileRequired"和"FileAllowed"验证器,用于限制上传的文件类型。

  2. 在视图函数中,获取用户上传的图片数据并将其保存到数据库中。可以使用"pic.read()"方法获取图片的二进制数据。

  3. 在数据库操作完成后,记得提交数据库事务,保存修改。

下面是修改后的代码示例:

# models.py
class Product(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(30), nullable=False)
    pro_No = db.Column(db.String(30), nullable=False)
    image = db.Column(db.LargeBinary, nullable=False)
    ...


# forms.py
from flask_wtf.file import FileRequired, FileAllowed

class ProductForm(FlaskForm):
    name = wtforms.StringField('产品名称', validators=[Length(min=2, max=30, message='产品名称的字符数量在2-30之间')])
    pro_No = wtforms.StringField('产品型号', validators=[Length(min=2, max=30, message='产品型号的字符数量在2-30之间')])
    pic = wtforms.FileField('产品图片', validators=[FileRequired(), FileAllowed(['png', 'jpg', 'gif', 'jpeg'], '仅支持PNG,jpg,gif,jpeg格式图片上传')])  # 图片
    title = wtforms.StringField('简介', validators=[Length(max=30, message='产品简介的字符数量不能大于30')])
    body = wtforms.StringField('产品详情', validators=[Length(max=500, message='产品名称的字符数量不能大于500')])
    type_id = wtforms.SelectField('产品类型')


# views.py
def post(self, id=None):
    form = ProductForm(request.form)
    pro = Product() if not id else db.session.query(Product).get(id)
    if form.validate_on_submit():
        pic = form.pic.data  # 获取上传的图片数据
        picname = form.pic.data.filename
        image = pic.read()  # 读取图片的二进制数据
        form.populate_obj(pro)
        pro.image = image  # 保存图片数据到数据库
        if not id:
            db.session.add(pro)
        db.session.commit()
        return redirect(url_for('products_page'))
    return render_template('product_form.html', form=form)

问题2: 如果数据库中保存的是图片的路径,那么在前端如何调用这个图片并显示在浏览器中?

解决方案: 1. 在模板中使用Flask内置的"send_from_directory"函数来返回图片文件。

  1. 创建一个静态文件夹,用于保存上传的图片文件,并在Flask应用中指定静态文件夹的路径。

  2. 在模板中使用"{{ url_for('static', filename='uploads/products/' + pro.pic) }}"来获取图片文件的URL,并将其赋值给src属性展示在浏览器中。

下面是修改后的代码示例:

# app.py
app = Flask(__name__, static_folder='static')
app.config['UPLOAD_FOLDER'] = 'uploads/products'


# views.py
from flask import send_from_directory

@app.route('/uploads/products/<filename>')
def uploaded_file(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename)


# product.html
<img src="{{ url_for('uploaded_file', filename=pro.pic) }}" alt="Product Image">

请注意,以上代码只是示例,请根据自己的项目结构和实际需求进行相应的调整和修改。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^