Flask url_for serving images and nginx - python

I have a router
#app.route('/images/<filename>')
def images(filename):
send from(os.path.join('uploads', filename))
My images are saved in some directory called 'uploads'. And I configure nginx to serve static files.
My question is when I use url_for('images', filename='1.jpg') in jinja template, which should generate something like src="/images/1.jpg" in browser, if the user click this link, will nginx serve the file or flask serve it?
Another example:
when using url_for('static', filename='style.css') in template, is nginx serving it?

The solution shall work well, if follows these rules:
you know exactly what static files you are going to be served
your jinja based templates are generating proper links to these files
ngingx is properly configured to serve these static files
Under these (production) conditions, your Python code shall not get requests to these static files as they are served by nginx.
This is desired behaviour, as it off-loads python application by nginx, which can serve those files much more efficiently.

Related

Serve react build as a template in flask

I want to serve a react project with Flask.
I need the index HTML to be served as a flask template so I can pass in a variable from Flask,
and the other static files (css, js, favicons) as normal static files.
How can I achieve that?
Edit: I just had the html sent as a flask template and put the static files into a folder which I declared as the static dir in flask.
As far as I know, you can not do that. Flask uses template htmls that are rendered on the server. Now if you ask whether can you code a react renderer for server-side rendering with Python/flask?, might be possible, I guess. But people built big companies around this idea, for example Vercel. So better team up. What you can do though you can make flask and react communicate through different ports. i.e. code your Flask back-end as a rest-api and build the react front-end.

Redirect to a folder in Django

Django currently has a complete system for routing urls.
But I have a very specific situation where I am using django but actually need to use urls like in classic PHP language.
For example:
The url - localhost/reader/theeffort should take me to a folder called theeffort where I have my files index.html, 1.html, 2.html, 3.html
and so on!
Now all these files should be accessible by localhost/reader/theeffort/*.html and not by Django's default url system. Is this possible to achieve that? If yes, how?
This isn't a thing you would do with Django's URLs. If you just want to serve HTML files within a folder, they are static files; they should therefore be served by the web server itself, eg Apache. You just need to configure an alias in the Apache conf to point to the folder where the static files are.

Using Django for a website without separating static files

I want to move my website to django which has a lot of images and css files linked to it. Also it uses Application cache for caching the static files.Since I have other apps working on the django I want to move this static one also to the django.So is it possible to run a webpage without rendering the static files dynamically and use the page as static webpage only(static files path relative to html not using django's static folder)? How to do this?
Assuming the HTML is also static, you should just move everything (HTML and relative files) to a static folder (no need to separate the HTML template since it is static as well), and then you can map it to any URL you want using your web server, e.g. you can put them inside {{ STATIC_ROOT }}/my-page/, and map example.com/my-page/ to that folder on the filesystem
Run collectstatic, Django will copy/generate the static files into your STATIC_ROOT folder on the filesystem https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#collectstatic
Then use a web server like Apache or Nginx to serve your /my-page URL directly without hitting your Django app. (set in Django with STATIC_URL), while the other requests are forwarded to your Django app
So e.g. your Django app will run on 127.0.0.1:8000, while nginx runs on the default HTTP/HTTPS port, and uses e.g. proxy_pass to talk to your Django app for the dynamic content
http://wiki.nginx.org/HttpProxyModule

Static assets don't show up for flask on elastic beanstalk

How do you get aws elastic beanstalk to recognize your static assets in your flask app? I did the standard /.ebextensions/python.config couple of YAML lines a la:
option_settings:
"aws:elasticbeanstalk:container:python:staticfiles":
"/static/": "static/"
All of my calls to assets in templates are wrapped in "{{url_for('static', filename='img/office.jpg')}}" type things.
But no images, styles or javascript shows up on page load. Here is an example log file 404.
IP - - [25/Feb/2013:21:48:13 +0000] "GET /static/css/bootstrap.css HTTP/1.1" 404 328 "http://xyz.elasticbeanstalk.com/"
Am I missing something obvious? Everything runs great on my local, just static assets dont load once i git aws.push
It can be done also through Elastic Beanstalk Panel:
Configuration -> Software Configuration - > Static Files
and then
just as an alternative option
As of this writing, after spending many hours fighting with AWS EB's config, I gave up trying to make the static files work the way we all expect and updated my Flask app creation to:
app = Flask(__name__, static_url_path='/s')
This renders urls like /s/scripts/my-script.js and since I always use url_for('static', ...) in my code and templates, everything continued to work outside of AWS as well.
Update on 9/30/2013: I can pretty much guarantee that the staticFiles settings are completely ignored in AWS EB's Python container.
The change I suggested above has the undesirable downside of routing all static file requests through Flask (maybe, more accurately, WSGI.) That's not very hard to fix, though.
Create an Apache conig file at your project root, named app-httpd.conf:
Alias /s /opt/python/current/app/static
<Directory /opt/python/current/app/static>
Order allow,deny
Allow from all
</Directory>
This config tells Apache to take over any requests for URLs starting with /s, same prefix we chose for our static files, and serve files from our app's static folder.
Create this file at .ebextensions/custom-apache.config:
container_commands:
add_apache_conf:
command: "cp app-httpd.conf /etc/httpd/conf.d"
This file will be used during the app deployment and will copy the new .config file to a directory from which Apache is configure to load all .config files it sees.
4+ years later, I'm able to get static files working using:
(file: .ebextensions/WHATEVER_NAME.config)
option_settings:
- namespace: aws:elasticbeanstalk:container:python
option_name: StaticFiles
value: /static/=PATH/FROM/MY/APP/BASE/DIR/TO/STATIC/DIR/
...in my case, this was
value: /static/=distrib/static/
I found that changing my
app = Flask(__name__)
to
app = Flask(__name__, static_url_path='/static')
was neither necessary nor sufficient. When I only set static_url_path but not StaticFiles, it didn't work; when I set StaticFiles but not static_url_path, it worked fine.
<sarcasm>Elastic Beanstalk is super straightforward and well documented!</sarcasm>
I spent a goodly amount of time trying to figure this out and sort through these suggestions. I've made comments on the answers that were still relevant in 2020. Here's the TL;DR of the solution I encountered:
The static files section in the Modify Software screen under the Configuration left navigation pane on the Elastic Beanstalk UI sets the property aws:elasticbeanstalk:container:python:staticfiles. This configuration does not map to the static_url_path which Flask needs to find the static assets.
The correct property to set is StaticFiles, which can be set by adding a .config file to the .ebextensions directory.
Read more here.
A strange thing that I found to solve this issue was editing my .gitignore file. It had included removing the /dist folders, and that included the dist folders that my CSS was generated into. So the css files were actually missing when I deployed.
Hope this may help anyone who might be in the same boat.
This problem baffled me for a bit because it worked locally. No need to change config. I change line 1 to line 2 in my html file and it worked. Keep static folder in root directory and also keep config at /static/:/static/.
1 <link rel="stylesheet" href={{url_for('static',filename='style.css')}}/>
2 <link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='style.css') }}">
may be the quotes around the href.
I tried Myles Baker's solution, but did not work as upon deployment I received the error -
ERROR Invalid option specification (Namespace: 'aws:elasticbeanstalk:container:python', OptionName: 'StaticFiles')
I ended up using the following code in my .ebextensions/WHATEVER_NAME.config -
option_settings:
aws:elasticbeanstalk:environment:proxy:staticfiles:
/html: statichtml
/images: staticimages
Which is a straight copy/paste from here - https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environment-cfg-staticfiles.html
I had a similar problem where, strangely enough, all files from static/img/ were being served, but anything in static/css/ or static/js/ were simply not being served.
To fix this I opened .elasticbeanstalk/optionsettings.app-env from the root directory of the Flask source and edited this block of code to be
[aws:elasticbeanstalk:container:python]
NumProcesses=1
NumThreads=15
StaticFiles=/static/.*=
WSGIPath=application.py
[aws:elasticbeanstalk:container:python:staticfiles]
Note that StaticFiles actually takes a regular expression, so in /static/.* the .* allows for any path after /static/

Best way to structure a site with media to keep it separate from the base code. ( Opinion based )

I've recently have taken a new server under my wing that has an interesting installation of django on it. The previous developer mixed in the media uploads with the static content and in other modules created it's own directory on the root file level of the project. My first reaction to this was general annoyance. ( I'm a huge fan of modular development. ) However after working to 'correct,' it's raised a question.
Even though this question is tagged with django, feel free to post response according to java and asp.net.
How do you set up your static files? Do you stack everything inside a static directory or do you take the time link each modular independently?
One of my tricks for every django app I start is, in the init.py of said app I put the following.
import os
from django.conf import settings as djsettings
TEMPLATES_DIR = (os.path.join(os.path.dirname(__file__),'./templates'),)
djsettings.TEMPLATES_DIR += TEMPLATES_DIR
I don't think your trick is really needed (anymore).
If you use django.template.loaders.app_directories.Loader (docs)
you can put a template dir in your app dir and Django will check it for your app-specific templates
And starting with Django 1.3 you can use the staticfiles app to do something similar with all your static media files. Check the docs for the staticfiles-finders
So finally, thanks to the collectstatic management command, you're now able to keep your static media files modularized (for easier development and distribution), yet you still can bundle them at a centralized place once it is time to deploy and serve your project.
Right now I'm in the habit of putting a static folder in each app directory containing its static files. I keep templates in each app directory under templates. I alias the static path when putting the app behind nginx or apache.
One thing that I'm starting to do more of is putting static files such as javascript, css, or images behind a CDN like S3.

Categories