Why is it suggested to use a different service to host static files (like nginx or apache) for django? - django

I've seen many questions on stackoverflow about handling static files in django during deployment. I saw that many answers said something like this - "With debug turned off Django won't handle static files for you any more - your production web server (Apache or something) should take care of that."
Why can't we use the server hosting the django project to host the static files too?

Static files don't require any kind of logic or processing. It is more efficient to deliver them directly to the end-user directly from disk via a web server, rather than running them through the middle layer of Django. That middle layer (such as gunicorn, uwsgi, or mod_wsgi) is what allows things like views to be processed and for the ORM to connect with a database. Since static files require none of that, bypassing it is the most efficient. The same is true for media files that are uploaded by the end user. Good luck!

Related

Strategies for deploying Django App

I have a question that is probably more general than django-related development. The background is quite simple:
I am working on a project whose pages are mostly associated with a web application (this is what I am using Django for). In addition to the app-related pages, however, there are quite a few auxiliary pages (like a landing page, a faq page, a contact page, etc.) that have basically nothing to do with the web app.
What is the standard strategy for deploying such a project? It seems flawed to route requests to these static pages through Django. What seems to make sense is running two servers: one responsible for running the Django app and a a separate server that is responsible for serving the static pages (including, perhaps, the static content used by the app portion of the web site) .
What are some guiding principles that should be employed when making these decisions?
It's not uncommon to run Django side by side with a static site or another CMS.
You would need a front end server to route the request to either the static content or a CMS.
There are two common strategies:
Use URL prefix to determine where to route (e.g. example.com/static/ to static files and example.com/ to Django). You would need a front end server to route the request to either the static content or a web app/CMS written in another framework/language (this is configured with Alias directive in Apache).
Put the application server and static file server on separate domain/subdomain (e.g. static.example.com to static and app.example.com to Django). You can do this by configuring a front end server to serve on a single machine (this is configured with VirtualHost on Apache) or as separate machine. In either case, you'd need to configure the DNS to point to your subdomains to the right machine(s).
The former is simpler to setup, but the latter allows you to scale better.
Servers commonly used for front-ending an application server includes Apache, Nginx, or uWSGI, but pretty much any production-quality web server can do it.
In fact Django's deployment documentation (e.g. Apache) would always instruct you to have your static files served by the front end server even in a Django only installations, as Django weren't designed for efficiently serving static contents unlike the front end web servers.
The django.contrib.staticfiles app is there to make it possible for Django to refer to a static file hosted on a different server and easily switch between serving static contents with Django's built-in server during development but with the front end server on production.

Why is django's development automatic static file server not suitable for production?

As stated in: https://docs.djangoproject.com/en/dev/howto/static-files/
When DEBUG is set to True, the server automatically serves the static file, but it states:
This method is grossly inefficient and probably insecure, so it is unsuitable for production.
But what exactly is inefficient and insecure about it? I just have a small-ish project on Heroku that I haven't set to "production" mode yet and I'm wondering what are the exact downsides.
Performance related reasons:
web servers are orders of magnitude better at serving static files.
AFAIK the development server is mono-threaded and can respond only one request at time, concurrent requests will block (most browsers make 4 concurrent requests trying to download assets in parallel).
Security related reasons:
using the app to serve static content is overkill (simplification is good for security)
the developers like to be on the safe side, so it is kind of a disclaimer
debug mode exposes a lot of information about the server
Django started in the news publishing industry where in general there is enough traffic to justify serving static content from a dedicated web server, probably the original developers have a bias for this arrangement.
That said, there are projects that replace the default development server by a more robust implementation based on gunicorn or tornado.
Kenneth (the author of requests, employed by Heroku) has a different opinion (source):
In reality, serving static files through Python/Django is fine for
production — those requests are no different than dynamic ones.
Performance will be fantastic, but not as good as nginx.
If you're that heavily concerned about efficiency then you shouldn't
be hosting those files on your server anyway, you'd be pushing them to
an CDN like S3+Cloudfront and the like.
Another benefit to this approach is development:production parity.
And on heroku, you can't use Nginx to server static files, actually you can't do it on most other PaaS too, I got the same problem on cloud foundry last year. But there is a workaround:
On Heroku, your application directly responds to HTTP requests,
instead of going through an additional web server like Apache or
Nginx.
We recommend most applications serve their assets strait from Django
or a CDN.
Django doesn't recommend serving static files in production because of
the design of its static file handler.
Luckily, there is a library called DJ-Static which makes uses a
production-ready WSGI asset server.
I've written up a guide for Django and Static Assets here:
https://devcenter.heroku.com/articles/django-assets
Read the following discussions for more details:
Serving static files for a Django app
serving static files via gunicorn

Media server vs normal server

I am designing an iphone forum application with django running in amazon ec2. Currently I am learning to deploy django using either nginx or apache. I am confused about media server and normal server. A lot of sources say that nginx is good for serving media files or static content, what does that mean? For normal group conversation/forum application, how does apache and nginx differ in performance etc? When is my mobile application serving dynamic content and when is it serving static content?
Googling will find you better results for a comparison between Apache vs Nginx than anyone on this site can give you. It is too broad of a question and can be highly subjective.
Media Files
Media in a django context generally refers to files that have been uploaded by end users. It is common to have a django view that initially uploads the users file, but then any future access to it is served by a traditional web server like nginx.See the docs for more info.
Static Files
Static in a django context refer to images, javascript and css files. While developing your site, the built-in django development server will serve these files for you. However, when moving to production you will want to use a traditional web server like apache to serve these files. See the docs for more details.
Dynamic Content
This would refer to the content (html, json, xml etc.) that is generated by the views that you write within Django.

django serving media files in production (comparing to PHP frameworks)

I'm a django newbie. I've read that all django projects, deployed in production environment, should serve media files (uploads) through web server such as apache. My question is - why is that?
There are lots of PHP frameworks - eg. symfony 1 and 2 - which don't follow the rule. Once you've made your app accessible through a web server, you don't have to change anything depending on the env you deploy. There is just the DOCUMENT_ROOT configured on the web server and somewhere inside this directory lies the upload directory - that's all. You can be sure that no one will access PHP, sql files and so on - thanks to the proper framework architecture and the document root. Why is it different in django?
edit: besides, preparing different code for different environments (e.g. this) is quite a bad approach, since you can't use exactly the same code to deploy a project in different envs (and the code from the link makes sense only for debug env.
Because with PHP your code is served from web server's public directories together with static and media files. So when you request any of these static files web server serves them directly without executing any PHP code along the way.
In Django your code is running separately and all requests are processed by python code in Django. This is inefficient to serve static files, it's more efficient to serve allow a web server like Apache or Nginx to serve them directly without going through any python code.

Serve Media Files Via Apache on a Django Development Server?

For some reason i can't figure out, other than the 'stupid' errors that keep creeping up when I try to access media files (files uploaded by the user) in my Django app, why I just can't server media files!
In this particular case, all I want for example is to be able to serve up images to the front that have been uploaded. My up correctly serves static files via /static/, but when I try to serve my /site_media/ files hell breaks loose! What could I be doing wrong?
So, after realizing that Django wasn't essentially crafted to actually handle media files, I decided to resort to using Apache via the recommended mod_python option like it is recommended to do in production. But I've never done this before, and am wondering whether this is worth the trouble on the development server.
Well, I know eventually I have to go down this path when I go production, and so will still have to learn how to do this, but what are the pros and cons for this route on the development server?
First, mod_python is not recommended. In fact, it's specifically recommended against. Use mod_wsgi instead.
Secondly, we have no possible way of telling what you're doing wrong when serving static media via the dev server, because you have provided no code or details of your setup.
Finally, there is no reason why you can't use Apache - or even better, a lightweight server such as nginx - and point it at your static directory only. Then, set STATIC_URL in your settings.py to the address served by that server. It makes no difference what port it is on while you're in development.
It is surely a pro since the django serves the requests faster without having to deal with the media.
A con is that, if and when you edit the media, you need to also restart the apache, for the media to refresh.
update based on your comment:
You can of-course easily do it. One simple way I practice this is, by using the nginx and symlinking the media folder into nginx sites-enabled and run nginx on port 80 (or any other).
You can set the MEDIA_URL in your settings, where you point it to the url with the appropriate port.