这是我想要实现的目标:
我希望能够通过包含多种不同类型字段(BooleandFields、StringFields 等)的表单来编辑数据库条目,其中有两个flask_wtf FileFields
我希望在我之前预先填充(使用文件名)本来已经上传了文件,所以当我只想更改其他字段中的某些条目时,我不必重新上传相同内容的 x 个副本。
这是我的立场:
当我输入表单进行编辑时,所有其他字段(FileFields 除外)都已正确预填充。我可以使用 Flask-Uploads 和 UploadSet 的组合上传文件。通过一个flask_wtf.file FileField
. 在我的数据库中,我将文件名和文件 url 保存为字符串。
我已经阅读了flask-wtf 文件上传以及WTForms 文档,我对我必须做的事情来模拟表单需要什么以便填充 FileField 好像我已经感到有点迷茫
以下是我正在使用的代码片段:
- 初始化文件
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_bootstrap import Bootstrap
from flask_uploads import UploadSet, configure_uploads
[...]
app = Flask(__name__)
[...]
csvfiles = UploadSet('csvfiles')
configure_uploads(app, (csvfiles,))
- 表格.py
这里有问题的文件字段是:“dive_posiview”和“dive_ctd”
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed, FileRequired
from wtforms import StringField, IntegerField, DecimalField, SubmitField,BooleanField
from app import csvfiles
from app.models import User
import re
class DiveForm(FlaskForm):
nb = IntegerField('Dive Number', validators=[DataRequired()])
max_depth = IntegerField('Maximum Depth', validators=[DataRequired()])
launch = StringField("Launch Position: XX°XX.XXXX'N / XX°XX.XXXX'E ", validators=[InputRequired(),validate_Lat_Lon])
recovery = StringField("Recovery Position: XX°XX.XXXX'N / XX°XX.XXXX'E ", validators=[InputRequired(),validate_Lat_Lon])
launch_datetime = DateTimeLocalField('Launch Time',format='%Y-%m-%dT%H:%M', validators=[InputRequired()])
recovery_datetime = DateTimeLocalField('Recovery Time',format='%Y-%m-%dT%H:%M', validators=[InputRequired()])
bottom_start_datetime = DateTimeField('Bottom start time',format='%H:%M', validators=[DataRequired()])
bottom_start_depth = IntegerField('Bottom start depth', validators=[DataRequired()])
bottom_end_datetime = DateTimeField('Bottom end time',format='%H:%M', validators=[DataRequired()])
bottom_end_depth = IntegerField('Bottom end depth', validators=[DataRequired()])
dive_time_total = DateTimeField('Dive total time',format='%H:%M', validators=[DataRequired()])
dive_time_bottom = DateTimeField('Bottom total time', format='%H:%M',validators=[DataRequired()])
dive_posiview = FileField('Posiview log', validators=[FileAllowed(csvfiles, 'CSV file only !')])
dive_ctd = FileField('CTD log', validators=[FileAllowed(csvfiles, 'CSV file only ! ')])
[...]
submit = SubmitField('Validate')
- 路线.py
@app.route('/cruises/<cruisename>/<diveId>/edit',methods=['GET','POST'])
def dive_edit(cruisename,diveId):
try:
c = Cruises.query.filter_by(name=cruisename).first_or_404()
d = Dives.query.filter_by(cruise_id=c.id,id=diveId).first_or_404()
if request.method == "POST":
form = DiveForm(formdata = request.form)
if form.validate_on_submit():
dive = d
dive.nb = form.nb.data
dive.max_depth = form.max_depth.data
dive.launch = form.launch.data
dive.recovery = form.recovery.data
dive.launch_datetime = form.launch_datetime.data
dive.recovery_datetime = form.recovery_datetime.data
dive.bottom_start_datetime = form.bottom_start_datetime.data
dive.bottom_start_depth = form.bottom_start_depth.data
dive.bottom_end_datetime = form.bottom_end_datetime.data
dive.bottom_end_depth = form.bottom_end_depth.data
dive.dive_time_total = form.dive_time_total.data
dive.dive_time_bottom = form.dive_time_bottom.data
dive_folder = cruisename+'/Dive'+str(form.nb.data)
filename_posiview = csvfiles.save(request.files['dive_posiview'],folder=dive_folder)
url_posiview = csvfiles.url(filename_posiview)
filename_ctd = csvfiles.save(request.files['dive_ctd'],folder=dive_folder)
url_ctd = csvfiles.url(filename_ctd)
dive.posiview_filename = filename_posiview
dive.posiview_url = url_posiview
dive.ctd_filename = filename_ctd
dive.ctd_url = url_ctd
dive.sampling_nets = form.sampling_nets.data
dive.sampling_shovel = form.sampling_shovel.data
dive.sampling_drill = form.sampling_drill.data
dive.sampling_niskin = form.sampling_niskin.data
dive.sampling_push_cores = form.sampling_push_cores.data
dive.sampling_he_sampler = form.sampling_he_sampler.data
dive.sampling_arm_action = form.sampling_arm_action.data
dive.sampling_GBS = form.sampling_GBS.data
dive.sampling_GBC = form.sampling_GBC.data
dive.sampling_IMGAM = form.sampling_IMGAM.data
dive.sensor_CTD = form.sensor_CTD.data
dive.sensor_CODA = form.sensor_CODA.data
dive.sensor_sonar = form.sensor_sonar.data
dive.sensor_MiniPos = form.sensor_MiniPos.data
dive.sensor_MiniPos_calibrated = form.sensor_MiniPos_calibrated.data
dive.action_device_deployed = form.action_device_deployed.data
dive.action_device_recovered = form.action_device_recovered.data
dive.action_mosaicing = form.action_mosaicing.data
dive.action_3D_imaging = form.action_3D_imaging.data
db.session.commit()
# execute jupyter convert script for that dive
if filename_ctd is not None and filename_posiview is not None:
summary_file_path = os.path.abspath(os.curdir)+'/app/static/jupyter/scientific_summary_dive'+str(form.nb.data)+'.html'
if not path.exists(summary_file_path) :
paths = "POSIVIEW_PATH="+csvfiles_path+'/'+filename_posiview
paths += " CTD_PATH="+csvfiles_path+'/'+filename_ctd
thread = threading.Thread(target=os.system, args=( (paths+" jupyter nbconvert --to html --execute app/static/jupyter/dive_scientific_summary.ipynb --output scientific_summary_dive"+str(form.nb.data)),))
thread.daemon = True
thread.start()
return redirect(url_for('cruise',cruisename=cruisename))
else :
form = DiveForm(obj = d)
# NOT WORKING
if os.path.isfile(csvfiles_path+'/'+d.ctd_filename) :
form.dive_ctd.data = d.ctd_filename
# NOT WORKING
if os.path.isfile(csvfiles_path+'/'+d.posiview_filename) :
form.dive_posiview.data = d.posiview_filename
return render_template('dive_new.html',title='edit dive',form = form , diveId = diveId)
except Exception as e:
flash(e)
return render_template("500.html")
我使用的版本是:
Python 3.8.2
Flask 1.1.1
Flask-Uploads 0.2.1
Flask-WTF 0.14.3
WTForms 2.3.1
谢谢您的帮助