pallets / flask

The Python micro framework for building web applications.
https://flask.palletsprojects.com
BSD 3-Clause "New" or "Revised" License
67.56k stars 16.15k forks source link

get_send_file_max_age doesn't work in blueprint #1691

Closed hongy19 closed 8 years ago

hongy19 commented 8 years ago

I have a small Flask program which serves static file by itself instead of nginx. I want to change cache time for png file by get_send_max_age function. It works in Flask class, but it doesn't work if I implement it in blueprint.

Python 3.5 Flask 0.10.1 Werkzeug 0.11.2

Flask implementation

class MyFlask(Flask):
    def get_send_file_max_age(self,name):
        print("my function works")
        print(name)
        if name.lower().endswith('.png'):
            return 0
        else:
            return Flask.get_send_file_max_age(self,name)
app = MyFlask(__name__)

Blueprint implementation

class MyBlueprint(Blueprint):
    def get_send_file_max_age(self,name):
        print("my function works")
        print(name)
        if name.lower().endswith('.png'):
            return 0
        else:
            return Blueprint.get_send_file_max_age(self,name)
test = MyBlueprint('test',__name__)
ThiefMaster commented 8 years ago

send_file has nothing blueprint-specific, so I'm pretty sure you cannot override it on a blueprint level.

But what you can do is checking request.blueprint (contains the name of the blueprint) in your custom MyFlask.get_send_file_max_age method and return something else based on the blueprint.


Edit: Just checked, according to CHANGES it should be supported in Blueprints (still seems weird) but it isn't..

hongy19 commented 8 years ago

hi ThiefMaster, according to Flask documentation, blueprint should support get_send_file_max_age function, but weird thing is example in blueprint part is still Flask class

get_send_file_max_age(filename) Provides default cache_timeout for the send_file() functions. By default, this function returns SEND_FILE_MAX_AGE_DEFAULT from the configuration of current_app. Static file functions such as send_from_directory() use this function, and send_file() calls this function on current_app when the given cache_timeout is None. If a cache_timeout is given in send_file(), that timeout is used; otherwise, this method is called. This allows subclasses to change the behavior when sending files based on the filename. For example, to set the cache timeout for .js files to 60 seconds:

class MyFlask(flask.Flask):
    def get_send_file_max_age(self, name):
        if name.lower().endswith('.js'):
            return 60
        return flask.Flask.get_send_file_max_age(self, name)

New in version 0.9.

rayalan commented 8 years ago

I just ran into this myself. The get_send_file_max_age() function on the blueprint is separate from the one on the main flask app. So you'd need do something like:

class MyBlueprint(flask.Blueprint):
    def get_send_file_max_age(self, name):
        # Repeat custom code here or else figure out how to call into the main app.
...
from somewhere import MyBlueprint
blueprint_example = MyBlueprint(...)

I agree it is confusing to have to customize the logic for each blueprint. It'd be a little easier if the blueprint could call into the main app, but I'm not sure it can do that.

prachikhadke commented 8 years ago
  1. Created requirements.txt with:

    Flask==0.10.1
    Werkzeug==0.11.2
  2. Created a virtualenv with python 3.5:

    mkvirtualenv temp -p /usr/local/bin/python3.5
  3. Installed dependencies:

    pip install -r requirements.txt
  4. Created flask_test.py and blueprint_test.py and ran them:

    #flask_test.py

    from flask import Flask
    
    class MyFlask(Flask):
       def get_send_file_max_age(self,name):
           print("my function works")
           print(name)
           if name.lower().endswith('.png'):
               return 0
           else:
               return Flask.get_send_file_max_age(self, name)
    
    app = MyFlask(__name__)
    with app.app_context():
       app.get_send_file_max_age('cube.png')
       app.get_send_file_max_age('scream.gif')

    #blueprint_test.py

    from flask import Flask
    from flask import Blueprint
    
    class MyBlueprint(Blueprint):
       def get_send_file_max_age(self,name):
           print("my function works")
           print(name)
           if name.lower().endswith('.png'):
               return 0
           else:
               return Blueprint.get_send_file_max_age(self,name)
    
    app = Flask(__name__)
    with app.app_context():
       test = MyBlueprint('test',__name__)
       test.get_send_file_max_age('cube.png')
       test.get_send_file_max_age('scream.gif')

    where cube.png and scream.gif are images from the internet.

  5. Ran flask_test.py and blueprint_test.py successfully. Could not reproduce the issue.
jeffwidman commented 8 years ago

@prachikhadke Thanks for this and all your other hard work at the Pycon Sprint today!

I'm going to go ahead and close this, if someone is still hitting this, please post example code to reproduce and we can take another look.