store file name in column when upload file using FileField wtforms

Viewed 1153

I have a table using the following code, which includes two columns: name and filename. My problem is that when I upload the file , then its file name is stored in the filename column. How do I do this? Now when I upload the file, 'None' is placed in the filename.i can only upload file or enter name in database,i think that problem is enctype="multipart/form-data". from flask_wtf import FlaskForm

from flask_wtf.file import FileField
from wtforms import StringField,SelectField,IntegerField
from wtforms.ext.sqlalchemy.fields import QuerySelectField
from wtforms.validators import DataRequired, Email, Length
class ContactForm(FlaskForm):

    name = IntegerField('name', validators=[Length(min=-1, max=100, message='You cannot have more than 100 characters')])
    filename = FileField()

this is my app.py:

def new_contact():
    '''
    Create new contact
    '''
    form = ContactForm()


    if  form.validate_on_submit():


        return render_template('web/new_contact.html',form = form)

        f = form.filename.data
        f.save(os.path.join("./static/upload/", f.filename))
        return redirect(url_for('new_contact'))
        print(f)



        my_contact = Contact()
        form.populate_obj(my_contact)
        db.session.add(my_contact)
        try:
            db.session.commit()
            # User info
            flash('Contact created correctly', 'success')
            return redirect(url_for('contacts'))
        except:
            db.session.rollback()
            flash('Error generating contact.', 'danger')

    return render_template('web/new_contact.html', form=form)
1 Answers

With the limited info you gave, I will try to implement the functionality you want.

Your ContactForm can stay like that:

class ContactForm(FlaskForm):

    name = IntegerField('File Name', validators=[Length(min=-1, max=100, message='You cannot have more than 100 characters')])
    filename = FileField()

Then you pass the form object to template, from custom flask route, lets call it for the purpose of explaining, contact route:

@app.route('/contact')
def contact():
    contact_form = ContactForm()
    return render_template('contact.html'
                            contact_form = contact_form)

And in your template, that I called in this example contact.html, you render your form:

<form action="" method="post" enctype="multipart/form-data">
    {{ contact_form.csrf_token }}
    {{ contact_form.name }}
    {{ contact_form.filename}}
    <input type="submit"/>
</form>

In this form, we want with action="" to POST data on the same route, that is, contact route. So in this example we should also validate data in contact() method of flask app. But what is enctype="multipart/form-data" you may be wondering ?

First result searching for what it is gave us results:

The enctype attribute specifies how the form-data should be encoded when submitting it to the server. Note: The enctype attribute can be used only if method="post".

And for multipart/form-data:

No characters are encoded. This value is required when you are using forms that have a file upload control.

Lastly, we update the flask app contact route like so:

@app.route('/contact')
def contact():
    contact_form = ContactForm()
    if form.validate_on_submit():
        f = contact_form.filename.data
        name = contact_form.name.data
        f.save(os.path.join("./static/contacts/", name))
        redirect(url_for('contact'))
    return render_template('contact.html'
                            contact_form = contact_form)

We've successfully collected data from a form, and saved file in contacts folder in static, with the name from a form. Maybe additionally we could use secure_filename from werkzeug.utils.

Related