Django folder structure issues - python

Coming from an Apache / php world there is something i can't figure out searching for django Development best practices :
With symfony2 framework (or even java Play!) you always have a "public" folder and the webserver only serve files from this folder. Obvious Strategy for security reason it is also clear during dev process to put public files in this folder.
In django it is not clear at all : from my readings it appears as good practice to have a static folder at root level PLUS a Media folder for UGC files and à template folder. No main "public" folder.
Can someone help me to clear my mind here ? Would't it be more secure to have one folder to contain all requests and protect the rest of the app ?
Tanks

There are two different types of 'static' files in django.
Bundled resources/assets with applications (css,javascript typically)
Any files uploaded by your users.
Since these are two different categories of static files, django offers two mechanisms to deal with them. As the first is more common than the second (you may not have an application that requires users to upload files), dealing with the first condition comes built in with django.
As per the standard layout, applications that require static files will include them in a directory called static within the application directory. Django will search for this directory inside any app that is in INSTALLED_APPS for static files. If you have files that are not tied to any app, you can put them in a separate directory. This directory should be added to STATICFILES_DIRS (a tuple) so django is aware of it.
Once you have done this, the collectstatic command will gather all the static files (from the static subdirectories in all applications in INSTALLED_APPS and any directory in STATICFILES_DIRS) and put them in a directory pointed to by STATIC_ROOT; this is so {{ STATIC_URL }} tags work correctly in templates.
Now, all you do is move/point/link the STATIC_ROOT directory so that its accesible from the web. Django expects that all files in STATIC_ROOT are accessible at the root URL that specified by STATIC_URL.
For user uploaded files, django is more hands off. All it really cares about is that you don't put your user uploaded files in the same place as the collectstatic command will be using to read its files - this means, that the MEDIA_ROOT cannot be a directory or subdirectory of STATICFILE_DIRS (if you have specified any directories here, typically this setting is undefined in vanilla django setups).
MEDIA_ROOT is a directory that django can manipulate by creating subdirectories under the root (see the FileField documentation for example).
MEDIA_URL is the URL prefix that points to the root for user-uploaded files. This is so that commands that generate automatic URLs for models work correctly.
As these are two different classes of static files, there are two different types of security and deployment requirements. For example, you might want to store user uploaded files in a S3 bucket but put your application's assets somewhere else.
This is why these two similar things are segregated in django.

You can copy all your static assets into a public/static folder with the command
> python manage.py collectstatic
provided you have set a static path in your manage.py
STATIC_ROOT = "~/mypath/public/static/"
Each app should have its own static assets.

Related

Css file not loading on Python Anywhere

I have recently begun making a Django project on PythonAnyhwere.
I have followed the entire tutorial provided by Django for including static files on the project. I have observed the programs work fine on a site with http, but does not work on a site with https.
What could be the reasons and how can I overcome this problem?
Edit : The site is working now, apparently, but I would still like an explanation as to why it WAS working differently, if anyone can provide.
to load your CSS files (or totally static files), you need to follow the steps below:
1- inside settings.py
STATIC_URL = '/static/'
STATIC_ROOT=os.path.join(BASE_DIR,'static')
MEDIA_ROOT=os.path.join(BASE_DIR,'media')
MEDIA_URL='/media/'
2-collect static files using bash console
python manage.py collectstatic
3-you need to enter the Static files directory inside the web tab
check the image below
static files python anywhere
4- reload your web app

Do I have to isolate my wsgi.py from my django project folder?

where should I place my wsgi.py?
Do I have to isolate it from my django project folder?
Should I move my django project folder outside of my home directory?
Currently I copied my django project folder to /home/username/djangosites/project/
and my wsgi.py is in the folder /home/username/djangosites/project/project/
In the same folder there are files like settings.py urls.py ...
From the modwsgi documentation:
"Note that it is highly recommended that the WSGI application script
file in this case NOT be placed within the existing DocumentRoot for
your main Apache installation, or the particular site you are setting
it up for. This is because if that directory is otherwise being used
as a source of static files, the source code for your application
might be able to be downloaded.
You also should not use the home directory of a user account, as to do
that would mean allowing Apache to serve up any files in that account.
In this case any misconfiguration of Apache could end up exposing your
whole account for downloading.
It is thus recommended that a special directory be setup distinct from
other directories and that the only thing in that directory be the
WSGI application script file, and if necessary any support files it
requires."
Let wsgi.py but don't make DocumentRoot anything like /home/username/djangosites/project/ which would expose your Python scripts source code, which would definitely be very helpful to malicious users.
All you need to expose is STATIC_ROOT (on STATIC_URL) and MEDIA_ROOT (on MEDIA_URL), you can use the Alias directive for that. Another solution is to use dj-static.

What's the point of Django's collectstatic?

In Django, the convention is to put all of your static files (i.e css, js) specific to your app into a folder called static. So the structure would look like this:
mysite/
manage.py
mysite/ --> (settings.py, etc)
myapp/ --> (models.py, views.py, etc)
static/
In mysite/settings.py I have:
STATIC_ROOT = 'staticfiles'
So when I run the command:
python manage.py collectstatic
It creates a folder called staticfiles at the root level (so same directory as myapp/)
What's the point of this? Isn't it just creating a copy of all my static files?
Collect static files from multiple apps into a single path
Well, a single Django project may use several apps, so while there you only have one myapp, it may actually be myapp1, myapp2, etc
By copying them from inside the individual apps into a single folder, you can point your frontend web server (e.g. nginx) to that single folder STATIC_ROOT and serve static files from a single location, rather than configure your web server to serve static files from multiple paths.
Persistent URLs with ManifestStaticFilesStorage
A note about the MD5 hash being appended to the filename for versioning: It's not part of the default behavior of collectstatic, as settings.STATICFILES_STORAGE defaults to StaticFilesStorage (which doesn't do that)
The MD5 hash will kick in e.g. if you set it to use ManifestStaticFilesStorage, which adds that behavior.
The purpose of this storage is to keep serving the old files in case
some pages still refer to those files, e.g. because they are cached by
you or a 3rd party proxy server. Additionally, it’s very helpful if
you want to apply far future Expires headers to the deployed files to
speed up the load time for subsequent page visits.
Django static files can be in many places. A file that is served as /static/img/icon.png could come from many places. By default:
FileSystemFinder will look for img/icon.png in each of STATICFILES_DIRS,
AppDirectoriesFinder will look for img/icon.png in the static subfolder in each of your INSTALLED_APPS. This allows libraries like Django Admin to add their own static files to your app.
Now: this only works if you run manage.py runserver with DEBUG=1. When you go live, the Django process will no longer serve the static assets. It would be inefficient to use Django for serving these, there are more specialised tools specifically for that.
Instead, you should do something like this:
find all of static files from every app
build a single directory that contains all of them
upload them somewhere (a static directory somewhere on your webserver or a third-party file storage)
configure your webserver (such as nginx) to serve /static/* directly from that directory and redirect any other requests to Django.
collectstatic is a ready-made script that prepares this directory for you, so that you can connect it directly to your deployment script.
In the production installation, you want to have persistent URLs. The URL doesn't change unless the file content changes.
This is to prevent having clients to have wrong version of CSS or JS file on their computer when opening a web page from Django. Django staticfiles detects file changes and updates URLs accordingly, so that if CSS or JS file changes the web browser downloads the new version.
This is usually achieved by adding MD5 hash to the filename during collectstatic run.
Edit: Also see related answer to multiple apps.
It's useful when there are multiple django apps within the site.
collectstatic will then collect static files from all the apps in one place - so that it could be served up in a production environment.

js and css files are not read in a DJANGO project

I am reformulating a previous question because I think it was formulated as a Python problem but it is a Django one.
I am installing a project from github called publicmarkup:
The main page displays on the browser but no media (neither js files, nor css files) are read loaded. There is a module called mediasync that seems to be necessary to display correctly the css and the js files of the templates.
I think this a configuration problem. Here's the link settings.py file, Here it could be find the root path of the media folder.
And here's the doc for the mediasync modulet explains how to configure static_url
But I didn't understand anything since I am a newbie to djnago
In Django you have to set up your own workstation serve static files, in both dev and live modes.
You can read about it here.
This explains how to serve static files in your dev environment.
In live mode you serve your static files directly via your end web server, usually either Apache or Nginx.

A web application to serve static files

I am thinking to design my own web app to serve static files. I just don't want to use Amazon services..
So, can anyone tell me how to start the project? I am thinking to develop in Python - Django on Openshift (Redhat's).
This is how ideas are going through in my mind:
A dashboard helps me to add/ delete/ manage static files
To setup API kind of thing (end point: JSON objects) so that I can use this project to serve my web apps!
As openshift uses Apache!, I am thinking to dynamically edit htaccess and serve the files.. but not sure whether it would be possible or not
Or, I can use django's urls.py to serve the files but I don't think djano is actually made for.
Any ideas and suggestion?
How about this:
Use nginx to serve static files
Keep the files in some kind of predefined directory structure, build a django app as the dashbord with the filesystem as the backend. That is, moving, adding or deleting files from the dashboard changed them the filesystem and nginx doesn't have to be aware of this dashboard.
Do not use dynamic routing. Just layout and maintain the proper directory structure using the databoard.
Optionally, keep the directory structure and file metadata in some database server for faster searches and manipulation.
This should result in a very low overhead static file server.

Categories