#python #html #flask #flask-wtforms #csrf-token
Вопрос:
Я новичок в Колбе. Я много читал, но не мог найти решения.
Когда я комментирую валидаторы FileField ( pic
), код работает просто отлично. С валидаторами — нет form.errors
, но все равно form.validate_on_submit()
ложно.
Редактировать:
- Если я использую только
FileAllowed
валидатор, тоform.validate_on_submit()
это верно, даже если тип файла не «png»… - Если я использую только
FileRequired()
валидатор,form.validate_on_submit()
это ложь.
Это важная часть main.py:
import os
from flask import Flask, render_template, request, redirect, url_for
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
from flask_wtf.file import FileField, FileRequired, FileAllowed
from flask_wtf.csrf import CSRFProtect,CSRFError
#from werkzeug.utils import secure_filename
app = Flask(__name__)
# Flask-WTF requires an encryption key - the string can be anything
app.config['SECRET_KEY'] = 'nydtnvbkadjshnvcksdnvcld'
app._static_folder = 'D:/a/b/c/static'
#app.config['UPLOAD_FOLDER'] = 'D:/a/b/c/uploads/'
app.debug = True
# Flask-Bootstrap requires this line
Bootstrap(app)
ANALYSIS_FOLDER = 'D:/a/b/c/analysis/'
########################## test ###########################################
class NameForm(FlaskForm):
name = StringField('Which actor is your favorite?', validators=[DataRequired()])
pic = FileField('Picture of actor:',
validators=[FileRequired(), FileAllowed(['png'], 'png files only!')]
)
submit = SubmitField('Submit')
@app.route('/test', methods=['GET', 'POST'])
def test():
form = NameForm(request.form)
print(form.errors)
print(form.validate_on_submit())
if form.validate_on_submit():
print('Hello')
# create a folder for the new dataset
new_n = dataset_number(ANALYSIS_FOLDER)
data_path = os.path.join(ANALYSIS_FOLDER, 'data' str(new_n))
print(data_path)
os.mkdir(data_path)
# save name
with open(os.path.join(data_path, 'name_of_actor.txt'), 'w') as text_file:
text_file.write(form.name.data)
uploaded_file = request.files['pic']
print(uploaded_file)
if uploaded_file:
print(uploaded_file.filename)
uploaded_file.save(os.path.join(data_path, 'file.png'),)
return redirect(url_for('home'))
#return f'''<h1> {form.name.data} is a great actor! </h1>'''
return render_template('test.html', form=form)
Это base.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
<style>
.formdesign {
background-color: #BFC9CA;
color: black;
margin: 10px;
padding: 5px;
}
</style>
{% block head %} {% endblock %}
</head>
<body style="background-color:#BFC9CA">
{% block body %} {% endblock %}
</body>
</html>
и это test.html:
{% extends 'base.html' %}
{% block head %}
<title>Test</title>
{% endblock %}
{% block body %}
<h1>Test!</h1>
<form method="POST" action="" enctype="multipart/form-data">
{{ form.csrf_token() }}
<div class="form-row">
<div class="form-group col-md-6">
{{ form.csrf_token() }}
<label for=""> {{ form.name.label }}</label>
{{ form.name }}
<p> Names are super important. </p>
</div>
<hr>
<div class="form-group col-md-6">
{{ form.csrf_token() }}
<label for=""> {{ form.pic.label }}</label>
{{ form.pic }}
<p> Pictures are also super important. </p>
</div>
<div class="form-group">
{{ form.csrf_token() }}
{{ form.submit(class="btn btn-primary")}}
</div>
</div>
</form>
{% endblock %}
Ответ №1:
В полях указаны ошибки WTForms. Если вы хотите получить к нему доступ, вам необходимо использовать form.pic.errors
Проверьте документацию, например: https://flask-wtf.readthedocs.io/en/0.15.x/quickstart/#validating-forms
Комментарии:
1.
form.pic.errors
также пусто — ошибок нет.2. Что, если вы сделаете
form = NameForm()
это вместоform = NameForm(request.form)
этого ? (как в официальной документации). Кроме того, старайтесь попадатьform.pic.errors
только послеform.validate_on_submit()
Ответ №2:
Я решил эту проблему с помощью загрузки колб.
Мое main.py
сейчас выглядит так:
import os
from flask import Flask, render_template, request, redirect, url_for
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
from flask_wtf.file import FileField, FileRequired, FileAllowed
from flask_uploads import UploadSet, configure_uploads, patch_request_class, IMAGES
ANALYSIS_FOLDER = 'D:/a/b/c/analysis/'
app = Flask(__name__)
# Flask-WTF requires an encryption key - the string can be anything
app.config['SECRET_KEY'] = 'nydtnvbkadjshnvcksdnvcld'
app.config['UPLOADED_PHOTOS_DEST'] = ANALYSIS_FOLDER
app._static_folder = 'D:/a/b/c/static'
app.debug = True
# Flask-Bootstrap requires this line
Bootstrap(app)
photos = UploadSet('photos', IMAGES)
configure_uploads(app, (photos))
########################## test ###########################################
class NameForm(FlaskForm):
name = StringField('Which actor is your favorite?', validators=[DataRequired()])
pic = FileField('Picture of actor:',
validators=[FileRequired(), FileAllowed(photos, 'images only!')]
)
submit = SubmitField('Submit')
@app.route('/test', methods=['GET', 'POST'])
def test():
form = NameForm(request.form)
#if form.validate_on_submit():
if request.method == 'POST' and 'pic' in request.files:
print('Hello')
new_n = dataset_number(ANALYSIS_FOLDER)
data_path = os.path.join(ANALYSIS_FOLDER, 'data' str(new_n))
print(data_path)
os.mkdir(data_path)
# save e-mail
with open(os.path.join(data_path, 'name_of_actor.txt'), 'w') as text_file:
text_file.write(form.name.data)
filename = photos.save(storage=request.files['pic'], folder='data' str(new_n), name='pic.')
print(filename)
return redirect(url_for('home'))
return render_template('test.html', form=form)
И test.html
:
{% extends 'base.html' %}
{% block head %}
<title>Test</title>
{% endblock %}
{% block body %}
<h1>Test!</h1>
<form method="POST" action="{{ url_for('test') }}" enctype="multipart/form-data">
{{ form.csrf_token() }}
<div class="form-row">
<div class="form-group col-md-6">
{{ form.csrf_token() }}
<label for=""> {{ form.name.label }}</label>
{{ form.name }}
<p> Names are super important. </p>
</div>
<hr>
<div class="form-group col-md-6">
{{ form.csrf_token() }}
<label for=""> {{ form.pic.label }}</label>
{{ form.pic }}
<p> Pictures are also super important. </p>
</div>
<hr>
<div class="form-group">
{{ form.csrf_token() }}
{{ form.submit(class="btn btn-primary")}}
</div>
</div>
</form>
{% endblock %}