AttributeError: 'FlaskS3' object has no attribute 'url_for'

Question:

I’m building a flask application that deploys to AWS Lambda using zappa and I’m trying to use Flask-s3 to handle the static files. I’ve never used [Flask-S3][1] before and it seemed fairly simple but I’m getting…

AttributeError: 'FlaskS3' object has no attribute 'url_for'

They way I understand it you just need to replace your static url’s with url_for like so:

app.config['FLASKS3_BUCKET_NAME'] = 'mybucketname'
s3 = FlaskS3(app)

s3.url_for('static/file.jpg')

This isn’t working so clearly I’m doing something wrong but there is almost nothing online troubleshooting Flask-s3. Anything helps.

app = Flask(__name__)
Bootstrap(app)
app.config['FLASKS3_BUCKET_NAME'] = 'mybucketname'
s3 = FlaskS3(app)
MAILGUN_API_KEY = 'key'
auth = ('api', MAILGUN_API_KEY)


@app.route("/", methods=['GET', 'POST'])
def index():
    context = {
    'image': url_for('static/property_home.jpeg'),
    'heading': 'We sell property - At a discount!',
    'landing_video': url_for('static/intro.mp4')
    }
    form = forms.OptIn()
    if form.validate_on_submit():
        validate = requests.get(
            "https://api.mailgun.net/v3/address/private/validate",
            auth=auth,
            params={"address": form.email.data})
        if validate.json()['did_you_mean'] is not None:
            flash('Did you mean {}?'.format(validate.json()['did_you_mean']))
        elif validate.json()['is_valid'] == True and validate.json()['is_role_address'] == False and validate.json()['is_disposable_address'] == False:
            r = requests.post(
            "https://api.mailgun.net/v3/lists/YOUR_DOMAIN_NAME/members",
            auth=auth,
            data={'subscribed': True,
                  'address': form.email.data})
            if r.status_code == 200:
                requests.post('https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages',
                    auth=auth,
                    data={"from": '[email protected]',
                        "to": form.email.data,
                        "subject": "Welcome to Spokane Discount Properties",
                        "html": open('templates/indoc.html'),
                        "o:tag": 'indoctrinated'})
                flash('Thanks, we will notify you when we have more properties')
            else:
                flash('You are already subscribed, we will notify you when more properties are available')
        else:
            flash('Holy guacamole! Best check yo self, this is not a valid email.')
    return render_template('index.html', form=form, context=context)
Asked By: freefly0313

||

Answers:

From the doc here

In terms of getting your application to use external Amazon S3 URLs
when referring to your application’s static assets, passing your Flask
object to the FlaskS3 object is all that needs to be done.

The extension takes care of handling the url_for for you. So you might not need to call it directly.

Internally, every time url_for is called in one of your application’s
templates, flask_s3.url_for is instead invoked. If the endpoint
provided is deemed to refer to static assets, then the S3 URL for the
asset specified in the filename argument is instead returned.
Otherwise, flask_s3.url_for passes the call on to flask.url_for.

change this:

context = {
    'image': url_for('static/property_home.jpeg'),
    'heading': 'We sell property - At a discount!',
    'landing_video': url_for('static/intro.mp4')
    }

to:

context = {
    'image': url_for('static', filename= 'property_home.jpeg'),
    'heading': 'We sell property - At a discount!',
    'landing_video': url_for('static', filename='intro.mp4')
    }
Answered By: Mekicha