Django static files in production not loaded - django

I have a problem with static files in my Django application.
I create a simple blog app with Django REST Framework and Angular 6. It's working fine in my local development environment, but I have a problem with deploying it to production. The thing is, the app is loading (I know that because the root route is a redirection to /app and I am being redirected correctly) but there are no static files loaded.
Here is part of my configuration related to the static files:
STATIC_URL = '/static/'
BASE_DIR = os.path.join(
os.path.dirname(os.path.dirname(__file__)), '..', '..', '..'
)
STATIC_ROOT = os.path.join(BASE_DIR, 'app', 'static')
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'frontend'),
]
INSTALLED_APPS = [
...
'django.contrib.staticfiles'
...
]
The paths are correct, I triple-checked them to be sure. And here are routes configured in Django application:
urlpatterns = [
url('^api/', include(api_patterns)),
url('^admin/', admin.site.urls),
url('^app/', serve, kwargs={'path': 'index.html'}),
url('^$', HomepageView.as_view(), name='homepage-redirection'),
]
I am able to run manage.py collectstatic without any errors and all static files are correctly copied to the static directory. Static files for admin application are not loaded correctly as well. Here is a rough structure of directories in my project:
├── app
│   └── (python code here)
├── frontend
│   └── (angular code here)
├── media
│   └── (empty for now)
└── static
  └── (static files for Django)
The application server is nginx with Phusion Passenger (this was configured by my the company I rent the server from). I don't really know what else I can add here. Does anyone have any idea what can be wrong here? Maybe some hint would be the fact that the API endpoints are not accessible. I have access to admin application, but not to API (both configured in the same urls file).

Related

Why Django can't find static folder in BASE_DIR?

I have these directories:
└── MY_FOLDER
├── MY_PROJECT
│   └── settings.py
│     
├── MY_APP
├── STATIC
│   └── style.css
├── MEDIA
└── manage.py
In the settings.py I've indicated:
BASE_DIR = Path(__file__).resolve().parent.parent
STATIC_URL = 'static/'
STATICFILES_DIR = (os.path.join(BASE_DIR,'static'))
When I
print(STATICFILES_DIR)
I get a path:
MY_FOLDER/STATIC - what is exactly I wanted.
But Django don't see any css there, in that folder.
I tried to put my css to MY_APP/STATIC and it started to work correctly. But I want to have it not in MY_APP but in BASE_DIR/STATIC. How to do it?
Or if it is impossible, how to make a correct path for STATICFILES_DIR to let it search my statics in all apps I'll add in the future. Not only in one app by doing this:
STATICFILES_DIR = (os.path.join(BASE_DIR,'MY_APP','static'))
Thanks.
Always look for the documentation, you are naming the directive wrong and it also should be a list.
STATICFILES_DIRS = [
BASE_DIR / "static",
]
Try this:
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
Note: your static folder must be lowercase and ensure that static folder must be inside project root not inside an app

Is there a better way to load Django static directories for multiple apps than this? Thank you

I currently have the following in settings.py:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
#add app-specific static directory
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'project/static'),
os.path.join(BASE_DIR, 'project/apps/blog/static/'),
os.path.join(BASE_DIR, 'project/apps/users/static/'),
os.path.join(BASE_DIR, 'project/apps/comments/static/'),
os.path.join(BASE_DIR, 'project/apps/categories/static/'),
)
Should I be doing this in one line? Thanks very much.
You can add custom static file finder that would sort you out, but generally if you have /static folder inside of the app it should be discovered by
django.contrib.staticfiles.finders.AppDirectoriesFinder
as documented
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
Source
A better practice is to put all your static files in the same folder in your root directory instead of each app:
# ...
├── app1
├── app2
├── project
├── manage.py
├── media
├── requirements.txt
├── static
│ ├── css
│ ├── icons
│ ├── img
│ ├── js
│ └── vendor
Then in your settings.py assign this variable:
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'), ]
staticfiles_dirs sets the directory and tells Django where to look up for your static files, in this example, our folder is named 'static' in our root directory, os.path.join will join the base directory(root) with static.
BTW STATIC_ROOT is usually used in a production environment, when you run 'collectstatic` command, all static files including your 3rd party apps will be copied to this 'staticfiles' folder.
Also, you can put templates of each app into the same folder in a similar way:
# root
└── templates
├── app1
├── app2
├── app3
├── base.html
└── index.html
And in your settings.py, add the directory of 'templates' folder.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': { # ...
],
},
},
]
Personally, I think this would be much cleaner.
You can reference my project for the file structure:
here

Django app on Azure not getting static files

Got my Django project on a Azure webapp, but when I call on SSH terminal:
Python manage.py collectstatic
It says 252 files copied but my static files are not visible on my templates and static folder in wwwroot its empty...Here's my wwwroot structure:
wwwroot
|---Myproject
|---manage.py
|---oryx-manifest.toml
|---hostingstart.html
|---static //With all my static files
├── myapp
│ ├── migrations
│ ├── __pycache__
│ ├── static
| | |---Images
| | | |--myimage.png
| | | |--myimage2.png
│ └── templates
And this is my settings.py:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
('myapp', os.path.join(BASE_DIR, 'myapp', 'static')),
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
Any idea why or what am I doing wrong ?, does Azure collect different ?
EDIT> When I go to my website my images don´t show...Im calling them like this on template:
{% load static %}
<img src="{% static 'Images/myimage.png' %}" /><br>
EDIT 2 /////
In wwwroot creates indeed a folder with all my statics, but when I load my template they don´t show, in wen console I get this error for myimage.png and myimage2.png :
Failed to load resource: the server responded with a status of 404 (Not Found)
Found it !!
Just had to add this: + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) to url patterns like this:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('myapp/', include('myapp.urls')),
path('admin/', admin.site.urls),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
And it did the trick, hope it helps to anyone else!!
Django does not serve static files in production mode.
The only time it serves static files is when you turn DEBUG = True which is in development mode and this is not recommended in a production setting.
Django recommends to serve static files via CND or any other webserver. However if your website is minimal and does not get high volume traffic you can serve your static files using Django whitenoise and here is how you do it.
The below solution works on python 3.7 and Django 3.2
Step 1: Install whitenoise package
pip install whitenoise
Step 2: Ensure your BASE_DIR looks like the below
BASE_DIR = Path(__file__).resolve().parent.parent
Step 3: Add these to your settings.py. If you get any errors try commenting out STATICFILES_STORAGE and check
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATIC_URL = '/static/'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
Step 4: WhiteNoise middleware should be placed directly after the Django SecurityMiddleware (if you are using it) and before all other middleware
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
# ...
]
Step 5: Ensure this is how you reference static files in your templates(also check if you have {% load static %} mentioned in your template
<link rel="stylesheet" type="text/css" href="{% static 'appname/styles.css' %}">
Step 6: Run collect static
python manage.py collectstatic
Step 7: Turn DEBUG = False and run the server to verify it works.
Some additional resources to read further:
whitenoise
Django on Azure - beyond "hello world"
Few points to note:
Below line will change
STATIC_ROOT = (os.path.join(BASE_DIR, 'Myproject/static_files/'))
to
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
You are using pointing to completely different folder here. Hence always empty You need the collectstatic command to copy files to
Project > static directory
Below remove the line os.path.join(BASE_DIR, 'static/')...
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static/'), #Not Required since you already mentioned it in STATIC_URL
('myapp', os.path.join(BASE_DIR, 'myapp', 'static')),
)
Reason:
STATIC_ROOT is the folder where static files will be stored after
using manage.py collectstatic
The absolute path to the directory where collectstatic will collect
static files for deployment.
If the staticfiles contrib app is enabled (default) the collectstatic management command will collect static files into this
directory. See the howto on managing static files for more details
about usage.
STATICFILES_DIRS is the list of folders where Django will search for
additional static files aside from the static folder of each app
installed.
This setting defines the additional locations the staticfiles app will
traverse if the FileSystemFinder finder is enabled, e.g. if you use
the collectstatic or findstatic management command or use the static
file serving view.
If issue still persists check your static file directory in apache mod_wsgi config file in the server if it is configured properly.
Check this link for help on that >> https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/modwsgi/
Cheers!!!
I would recommend checking out Whitenoise for serving your static files with Django. I haven't had an issue serving them since integrating Whitenoise. Try swapping it out with your current static file finders setup.
http://whitenoise.evans.io/en/stable/django.html

Django not serving static files while STATIC_ROOT configured

I have a cloned project and I need to serve the static files with Django itself. It is my first time serving static files this way (in the past I used Nginx/Apache to serving media and static files). here is my try to serve static files by Django itself in production:
1- Adding STATIC_URL and STATIC_ROOT to settings.py:
...
STATIC_URL = '/static/'
STATIC_ROOT = os.environ.get('DH_STATIC_ROOT_DIR', os.path.join(BASE_DIR, 'static/'))
2- project's directory tree:
├── my_project
│   ├── DH
│   ├── env
│   ├── apps
│   ├── manage.py
│   ├── README.md
│   ├── requirements.txt
│   ├── static
│   └── templates
3- running ./manage.py collectstatic and working well. here is static/ directory's tree after this command (from past some static file exists in static directory because this project is MVT and loading templates):
├── admin
├── css
├── fonts
├── js
├── media
└── plugins
4- let Django serve static in production( in urls.py):
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', index, name='index'),
path('admin/', admin.site.urls)
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
5- how html templates reference to static files:
{% load static %}
...
<link href="{% static 'plugins/global/plugins.bundle.css' %}" rel="stylesheet" type="text/css" />
For example, in Chrome (inspect) I can see the template page request to http://127.0.0.1:8000/static/media/logos/logo-6.png that static/media/logos/logo-6.png exist (all request to static files raise 404 HTTP status code). with this configuration not working even in DEBUG=True what I am doing wrong? Thank you in advance.
As documentation states, serve not suppose to be used in production. If you don't want to use nginx or apache, then consider using whitenoise. All you need to do is install it by pip install whitenoise and add these lines to middleware:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
# ...
]

How to serve collected static files with Django's development server?

I am trying to make Django's development server to serve static files that have been collected by the python manage.py collectstatic command. For now I failed.
My Django settings file declares this:
STATIC_ROOT = os.path.join(WWW_PATH, 'static')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(ROOT_PATH, 'front', 'public'),
os.path.join(ROOT_PATH, 'front', 'dist')
)
This makes the collectstatic command copying files from os.path.join(ROOT_PATH, 'front', 'public') and os.path.join(ROOT_PATH, 'front', 'dist') to STATIC_ROOT, and it works perfectly.
I was assuming that it would also tell Django to look for static files into the STATIC_ROOT directory, I was wrong. Even if the STATIC_ROOT directory does not exists, Django is able to serve the static files. But if the os.path.join(ROOT_PATH, 'front') is missing, Django no more serve the static files.
This shows that Django continues to serve static files from the sources directories and not from STATIC_ROOT.
So I would like to know if there is a way to instruct Django's development server to serve static files from STATIC_ROOT. Any hint?
EDIT:
After #e4c5 's answer I modified my root urls.py like this:
static_patterns = [
url(r'^$', TemplateView.as_view(template_name='index.html'))
]
urlpatterns = [
url(r'^', include(static_patterns)),
url(r'^admin/', admin.site.urls),
url(r'^api/resa/', include('reservation.urls')),
url(r'^api/auth/', include('authentication.urls')),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
unfortunately, it does not have the expected result and Django does not find static files in STATIC_ROOT, I doubt that it actually looks for static files in STATIC_ROOT.
here is what I can see in the console when accessing to the index page:
[04/Jun/2017 16:18:05] "GET / HTTP/1.1" 200 1411
[04/Jun/2017 16:18:05] "GET /static/style/index.css HTTP/1.1" 404 1759
[04/Jun/2017 16:18:05] "GET /static/style/react-datetime.css HTTP/1.1" 404 1786
[04/Jun/2017 16:18:05] "GET /static/style/react-big-calendar.css HTTP/1.1" 404 1798
[04/Jun/2017 16:18:05] "GET /static/script/bundle.js HTTP/1.1" 404 1762
here are the content of the settings variables:
>>> from django.conf import settings
>>> settings.WWW_PATH
'/home/tryph/PycharmProjects/resa/www'
>>> settings.STATIC_ROOT
'/home/tryph/PycharmProjects/resa/www/static'
>>> settings.STATIC_URL
'/static/'
here is the content of the WWW_PATH directory:
/home/tryph/PycharmProjects/resa/www
└── static
├── admin
│   [...]
├── favicon.ico
├── index.html
├── rest_framework
│   [...]
├── script
│   └── bundle.js
└── style
├── index.css
├── react-big-calendar.css
└── react-datetime.css
This is done using static.serve
There may be files other than your project’s static assets that, for
convenience, you’d like to have Django serve for you in local
development. The serve() view can be used to serve any directory you
give it. (This view is not hardened for production use and should be
used only as a development aid; you should serve these files in
production using a real front-end web server
Change your urls.py like this:
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)