最近学习使用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"的列,用于保存图片的二进制数据。
在表单中将图片字段改为"FileField"类型,并且添加"Wtforms FileRequired"和"FileAllowed"验证器,用于限制上传的文件类型。
在视图函数中,获取用户上传的图片数据并将其保存到数据库中。可以使用"pic.read()"方法获取图片的二进制数据。
在数据库操作完成后,记得提交数据库事务,保存修改。
下面是修改后的代码示例:
# 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"函数来返回图片文件。
创建一个静态文件夹,用于保存上传的图片文件,并在Flask应用中指定静态文件夹的路径。
在模板中使用"{{ 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">
请注意,以上代码只是示例,请根据自己的项目结构和实际需求进行相应的调整和修改。