Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Christian Basile
Christian Basile
2,067 Points

str object does not have filename ( when in flask , trying to upload pictures)

Hi There,

This question is based on the Social Network with Flask course. I would really appreciate your help in this , if you can. I am having trouble uploading files /save.I tried to in the registration form add FileField() , but I experience problems. I would really appreciate the help, the error is something about filename not in str, for some reason, form.photo.data somehow is not being detected. I read the wtf documentation, it seems I am respecting their requirements, I somehow feel the error is in the html part of it, I even tried with html input file instead of Jinja 2 {{ form.photo.data.label }} {{form.photo.data }} respectively.

@app.route('/register', methods=('GET', 'POST'))
def register():
    form= forms.RegisterForm()
    if form.validate_on_submit():


        file= form.photo.data

        #filename = secure_filename(form.photo.data.filename)
        #object_name = filename
        UPLOAD_FOLDER= 'static'
        Key=form.username.data;
        #Filenamepath=os.path.join(UPLOAD_FOLDER, file.filename)
        Filenamepath=os.path.join(UPLOAD_FOLDER, file)
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        s3_client.upload_file(Filenamepath, BUCKET, Key, ExtraArgs=None, Callback=None, Config=None)
        flash("Yah , you registered!", "success")
        models.User.create_user(username=form.username.data, email= form.email.data, password=form.password.data,gender=form.gender.data, age=form.age.data, aboutme=form.aboutme.data)
        return redirect(url_for('index'))
    return render_template('register.html', form=form)
<html>
<head>
<title>Form!</title>
</head>
<body>
<h1>Our form will be here!</h1>
<form method="POST" action="{{ url_for('form') }}" enctype = "multipart/form-data">
    {{ form.csrf_token }}
    {{ form.username.label }}
    {{ form.username }}
    {{ form.email.label }}
    {{ form.email }}
    {{ form.password.label }}
    {{ form.password }}
    {{ form.gender.label }}
    {{ form.gender }}
    {{ form.age.label }}
    {{ form.age }}
    {{ form.aboutme.label }}
    {{ form.aboutme }}
    {{ form.photo.label }}
    {{ form.photo }}


    <input type="submit" value="Submit">
</form>
</body>
</html>

What I did was to remove the form.photo.label , and allowed users to log in first. Then, I created a separate form for images , and it worked. For some reason, if I include the photo in this form above it does not work, but when I separated photo in another form it worked. It will be nice to have it all in one. The issue is that form.photo.data is a string like name of file already.

class RegisterForm(Form):
    username = StringField(
        'Username',
        validators=[
            DataRequired(),
            Regexp(
                r'^[a-zA-Z0-9_]+$',
                message=("Username should be one word, letters, "
                         "numbers, and underscores only.")
            ),
            name_exists
        ])
    email = StringField(
        'Email',
        validators=[
            DataRequired(),
            Email(),
            email_exists
        ])
    password = PasswordField(
        'Password',
        validators=[
            DataRequired(),
            Length(min=2),
            EqualTo('password2', message='Passwords must match')
        ])
    password2 = PasswordField(
        'Confirm Password',
        validators=[DataRequired()]
    )

    gender = RadioField('Gender', choices = [('M','Male'),('F','Female')])
    age = IntegerField('Age')
    aboutme = TextAreaField('What you looking for?')
    #photo = FileField('Upload_Photo')    
    #upload = FileField('image', validators=[
     #   FileRequired(),
      #  FileAllowed(['jpg', 'png'], 'Images only!')
    #])

This is the form I was trying to do. Again thank you! If quick great, if not no worries, and let me know how to close it, as now it sort of works, but it will be nice to understand why it does not work if you have them all in one. Also, is hard to debug, not sure if "trace" or cookie can help debug.

AGAIN Thank you. Very new to flask myself fyi :) Thanks

FYI this one, works just fine, not sure why the above does not work

@app.route('/upload/<username>', methods=('GET', 'POST'))
def upload(username):

    form= forms.Photoupload()
    #filename='mama.jpg'
    #Filenamepath=os.path.join("./static/img/", filename)
    #print(Filenamepath)
    if form.validate_on_submit():
        UPLOAD_FOLDER= 'static'
        file= form.upload.data
        filename= secure_filename(file.filename)
        #print("HIIIIIII")
        Key=username;
        Filenamepath=os.path.join("./static/img/", filename)
        file.save(os.path.join("./static/img/", filename))
        s3_client.upload_file(Filenamepath, BUCKET, Key, ExtraArgs=None, Callback=None, Config=None)
        flash("Yah , you uploaded!", "success")
        #return redirect(url_for('index'))
    return render_template('uploads.html', username=username, form=form)

Thanks, I want to have only one form ideally for info + photos.

Josh Keenan
Josh Keenan
20,315 Points

Can you wrap your code snippets with 3 backtick characters, this one: `