'WTForms FileField has no 'filename' attribute

I am creating a website with Python Flask. However, when the user registers an account, I get this error:

'FileField' object has no attribute 'filename'

I have used the 'filename' attribute in my 'save_picture' function below:

def save_picture(form_picture):
form = UpdateAccountForm()
random_hex = secrets.token_hex(8)
_, f_ext = os.path.splitext(form.picture.filename)
picture_fn = random_hex + f_ext
picture_path = os.path.join(app.root_path, 'static/profile_pics', 'picture_fn')

output_size = (125,125)
i = Image.open(form_picture)
i.thumbnail(output_size)
i.save(picture_path)

form_picture.save(picture_path)

return picture_fn

This is the form that I have used the 'FileField' object in:

class UpdateAccountForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
email = StringField('Email', validators=[DataRequired(), Email()])
age = IntegerField('Age', validators=[DataRequired()])
picture = FileField('Update Profile Picture', validators=[FileAllowed(['jpg', 'png'])])
submit = SubmitField('Update')

def validate_username(self, username):
    if username.data != current_user.username:
        user = User.query.filter_by(username=username.data).first()
        if user:
            raise ValidationError('That username is taken. Please choose a different one')

def validate_email(self, email):
    if email.data != current_user.email:
        user = User.query.filter_by(email=email.data).first()
        if user:
            raise ValidationError('That email is taken. Please choose a different one.')


Solution 1:[1]

You ask for the input field itself. In order to access the sent data, the input field has an attribute called data. If you take this into account, the assignment would look like this.

_, f_ext = os.path.splitext(form.picture.data.filename)

The code for your endpoint will then look something like this.

@app.route('/upload', methods=['GET', 'POST'])
def upload():
    form = UpdateAccountForm()
    if form.validate_on_submit():
        # ...
        random_hex = secrets.token_hex(8)
        _, ext = os.path.splitext(form.picture.data.filename)
        img = Image.open(form.picture.data)
        img.thumbnail((125,125))
        img.save(os.path.join(
            app.static_folder,
            'profile_pics',
            f'{random_hex}{ext}'
        ))
        return redirect(url_for('index'))
    return render_template('upload.html', form=form)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Detlef