Django - Static files don't serve in production - python

My site works well in local but when I put it on my server, it can't load the static files. Here's my files.
settings.py
DEBUG=False
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
All my static are in /myproject/mymainapp/static
I've got another directory "static" of the root of my project by doing manage collectstatic in production.
Here's my nginx conf file :
[...]
root /home/user/site/mymainapp/;
[...]
location /static {
alias /home/user/site/mymainapp/static;
}
I've tried to set the path to my static directory in my root directory project but it don't make anything better.
My URLs patterns :
urlpatterns = [
[...] nothing relative to static files
]
Maybe I should add something in my URLs patterns ?
Thanks for your help :)

Related

What Does Django static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) Actually DO?

I am using Django 2.2. From the Django Managing static files documentation:
If you use django.contrib.staticfiles as explained above, runserver
will do this automatically when DEBUG is set to True. If you don’t
have django.contrib.staticfiles in INSTALLED_APPS, you can still
manually serve static files using the django.views.static.serve()
view.
This is not suitable for production use! For some common deployment
strategies, see Deploying static files.
For example, if your STATIC_URL is defined as /static/, you can do
this by adding the following snippet to your urls.py:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Note
This helper function works only in debug mode and only if the given
prefix is local (e.g. /static/) and not a URL (e.g.
http://static.example.com/).
Also this helper function only serves the actual STATIC_ROOT folder;
it doesn’t perform static files discovery like
django.contrib.staticfiles.
My Interpretation
static is a helper function that serves files from the STATIC_ROOT during development (is this True?)
static only works when debug = True
static only works with a local prefix like STATIC_URL = '/static/'
When DEBUG is set to True and I use and setup the staticfiles app as explained in the documentation, if I do python manage.py runserver to start the local server, the serving of static files will be handled automatically (true??)
My Questions
What EXACTLY does adding static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) to your project's urls.py DO?
Is it true that static serves static files locally from the STATIC_ROOT directory? To test this theory, after running collectstatic, I then deleted the static directories to see if the static files still load fine (from the STATIC_ROOT) and they DON'T! Why?
How can I verify that Django is loading the static files from my STATIC_ROOT location... and not the static directories in my project and apps??
Why is adding static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) to urlpatterns necessary if Django serves static files automatically (mentioned in documentation)?
Example
settings.py
DEBUG = True
...
INSTALLED_APPS = [
'django.contrib.admin',
...
'django.contrib.staticfiles',
'puppies.apps.PuppiesConfig'
]
...
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
STATIC_ROOT = 'c:/lkdsjfkljsd_cdn'
In all my templates, I'm using {% load static %}.
Then I do: python manage.py collectstatic
At this point, it doesn't seem to matter if I have the below in my urls.py or not - my static files still load BUT I don't know if they're coming from my project's static directories or my STATIC_ROOT (c:/lkdsjfkljsd_cdn):
if settings.DEBUG is True:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Lastly, if I delete those static directories in my project, all css, js and images don't work which leads me to believe that my Django project is loading static files from my project's static directories, NOT the STATIC_ROOT.
So, again, how can I tell Django to load the static files from my STATIC_ROOT location... and not the static directories in my project and apps?? OR, do I misunderstand that Django isn't supposed to load files from my STATIC_ROOT location locally?
*Edit (adding HTML image)
I think you are mixing up few things. Let me clarify.
static:
As per documentation, it provides URL pattern for serving static file. If you go to the implementation, then you will see:
return [
re_path(r'^%s(?P<path>.*)$' % re.escape(prefix.lstrip('/')), view, kwargs=kwargs),
]
What it does is, it removes forward slash from left of the prefix(ie converts /static/ to static/), and then there is a view(which is serve) who does the pulling files.
serve:
This function does the serving files. It will serve files from a document root.
runserver:
runserver command runs the django development server. If you have django.contrib.staticfiles installed in INSTALLED_APPS, then it will automatically serve static files. If you don't want to serve static, then use runserver --nostatic. collectstatic or STATIC_ROOT has no relation to this command.
collectstatic:
This command collects all static files from different STATIC_DIRS, and put them in folder which is defined by STATIC_ROOT. collectstatic is very useful in production deployment, when you are using a reverse proxy server like NGINX or Apache etc. NGINX/Apache/Varnish uses that folder (where collectstatic stored the static files) as root and serve static from it. It is not recommended to use runserver in production. You can use gunicorn/uwsgi to serve django. But gunicorn/uwsgi does not serve static files, hence using reverse proxy server to serve static files.
finally:
To answer your questions:
No you don't have to put that in your code, unless you are not adding django.contrib.staticfiles in your INSTALLED_APPS.
No
You don't need to. STATIC_ROOT is used for different purpose
It is not. But for serving MEDIA files, you can add the following pattern:
if settings.DEBUG:
urlpatterns += [
re_path(r'^media/(?P<path>.*)$', serve, {
'document_root': settings.MEDIA_ROOT,
}),
]
In production, media files should be served by reverse proxy server as well.

Django static files : use only /static/ directory

I have a Django live version in production and I develop in local with Django manager.py.
I'm not able to find the correct configuration settings for my static files.
All my static files are on a /static/ on the root of the project, because all the sub-apps use the same stylesheets and so on.
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'staticfiles'),
)
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
On my live version : it works because I've got an NGINX rule that allow access to /static/ directly.
But when I want to work on local, the static files are 404, with Debug True and False.
I don't see the interest for my needings of the staticfiles directory (but I can have a wrong mind here).
Is it possible to have all the static files in subdirectories in /static/ (css, img, js, etc.) and to set a workable settings on both local and live production without switching something in settings.py for deployment ?
Thanks for your help :)
I've found the solution :
After moving my static directory from the root directory of Django the folder of my main app, I made a collectstatic with that settings :
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'

serving static vs media in django 1.9

To serve the static files (CSS, JS), I set the settings:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
This means that all my static files need to be in the project root's static folder
/app1
/app2
/media
/static #They need to be stored here, all static files
/templates
urls.py
settings.py
manage.py
However, I am storing them in my app's static folder.
/app1/static/ # Storing the static files here
/app2/static/ #and here
/media/
/static/ # but not here
Still, Django is able to serve them, how is that possible?
I tried the same thing with media files; setting
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
and storing the media (images etc) files in each app's individual media dir. This time, Django did not serve the files and served them only when either I moved the files to the project root's media dir or changed the setting to MEDIA_ROOT = os.path.join(BASE_DIR, '<app_name>/media')
Why was I allowed to serve static files even when they weren't in the project root static dir but not the media files - they were only served from the root media dir.
Please read the documentation carefully - https://docs.djangoproject.com/en/1.9/ref/settings/#staticfiles-finders
It precisely states that django will search for static files in each app + the directory stated in settings.
Quoting as in the documentation -
The default will find files stored in the STATICFILES_DIRS setting (using django.contrib.staticfiles.finders.FileSystemFinder) and in a static subdirectory of each app (using django.contrib.staticfiles.finders.AppDirectoriesFinder). If multiple files with the same name are present, the first file that is found will be used.
While this is not true for media files. Django doesn't look for media files in subdirectories.

STATIC_ROOT = '/static/' collects my static files outside my workspace directory

i have in my settings.py used
STATIC_ROOT = '/static/'
to collect the static files
this is my static_path settings
STATIC_PATH = os.path.join(BASE_DIR,'static')
when i run the collect static code django makes a static folder outside my workspace folder,should't it collect all the static files in the static folder which i have already created?
I think you've confused the STATIC_ROOT and STATIC_URL and STATICFILES_DIRS setttings.
To tell Django to serve your static files from example.com/static/, set
STATIC_URL = '/static/'
You shouldn't set STATIC_ROOT = '/static'. This is telling Django to collect your static files in /static/ on your disk, which is outside of your workspace.
STATIC_ROOT is the directory where the static files will be collected. It should be something like
STATIC_ROOT = '/var/www/example.com/staticfiles/'
If you don't want to hardcode the directory, you could do something like:
STATIC_ROOT = 'os.path.join(BASE_DIR, "staticfiles"),'
You would then configure your webserver (e.g. Nginx or Apache) to serve the files in the STATIC_ROOT.
Finally, STATICFILES_DIRS is a list of locations that Django will search for static files when you run collectstatic. The files will be copied from that directory to your STATIC_ROOT. Therefore you need to make sure that the STATIC_ROOT is not included in STATICFILES_DIRS.
Basically you can create multiple 'static' folders for different applications of Django project and those can be used in development. But whenever you go to production servers and to serve the all static files from the same place then you need this functionality in which you can collect all static files from different directory to one directory out of your workplace.
project_name
- project_name
- static
- static files goes here which are common
- __init__.py
- settings.py
- urls.py
- application_name
- static
- static files goes here which are related to application only
- __init__.py
- settings.py
- urls.py
- static - This is common place where all static files will be placed after collectstatic command for productions only.
According above structure you can understand you can server static files using different server like CDN.
Let me know if you are not satisfied with answer. Thanks.

Django with ./manager runserver works well, while Django + uwsgi return 404

This si my settings.py about static in settings.py:
STATIC_ROOT = '/home/coat/www/site/app/static/'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
"/usr/lib/python2.6/site-packages/django/contrib/admin/static/",
# This is Django admin default static files
)
I user django server:
./manager runserver
Then I open the URL: http://localhost:8000/static/admin/css/base.css
It works very well.
But a open http://localhost/static/admin/css/base.css
It print '404'
I had restart Nginx and uwsgi for many times, but it dosen't works.
First things first, this is nonono:
STATIC_ROOT = '/home/coat/www/site/app/static/'
Never hardcode absolute paths, you're just making your settings file less portable and probably killing kittens. Adapt this to your needs:
import os.path
import posixpath
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
# fix STATICFILES_DIRS too
Now, to your question. django.contrib.staticfiles is fantastic but probably a little confusing at first.
You must understand the collectstatic command:
Collects the static files into STATIC_ROOT. [...] Files are searched by using the enabled finders. The default is to look in all locations defined in STATICFILES_DIRS and in the 'static' directory of apps specified by the INSTALLED_APPS setting.
With runserver, staticfiles are served automatically, but in production mode (DEBUG=False, real HTTP server like Nginx), you should run collectstatic to (re)build STATIC_ROOT
STATIC_ROOT: is the root path where the HTTP server should serve static files from.
STATIC_URL: is the root URL where the HTTP server should serve static files to.
STATICFILES_DIRS: other static directories, in addition to each app's "static" subdirectory. Because django.contrib.admin is a normal app with a "static" folder, there is no need to specify it in the settings.
Conclusion: if STATIC_ROOT resolves to /home/coat/www/site/app/static/, and STATIC_URL is /static/, then you should:
Run collectstatic management command
Configure Nginx to serve /home/coat/www/site/app/static/ on /static/, ie.:
location ^~ /static/ {
alias /home/coat/www/site/app/static/;
}
Reload nginx
In development the runserver command does some magic to serve your static files. In production you need to configure NGinx to do it. There are two chapters in the Django documentation I recommend you read:
Serving static files in production
Serving files (Deployment)
Especially the last link explains how you have to configure your NGinx to serve your static files.

Categories

Resources