Unable to load css while running django in docker - django

My docker-compose.yml
# pull official base image
FROM python:3.10-alpine
# set work directory
WORKDIR .
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt
# copy project
COPY . .
My Dockerfile is as follows:
services:
app:
build:
context: .
ports:
- "8000:8000"
command: >
sh -c "python3 manage.py runserver 0.0.0.0:8000"
redis:
image: redis:alpine
celery:
restart: always
build:
context: .
command: celery -A search worker -l info
depends_on:
- redis
- app
The tree structure of my project directory is as follows:
├── Dockerfile
├── Procfile
├── books
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── __init__.py
│ ├── models.py
│ ├── templates
│ │ └── search.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── docker-compose.yml
├── manage.py
├── requirements.txt
├── search
│ ├── __init__.py
│ ├── asgi.py
│ ├── celery.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── templates
├── base.html
├── home.html
└── registration
├── login.html
└── logout.html
My settings is as follows:
ALLOWED_HOSTS = ['0.0.0.0', '127.0.0.1', 'localhost']
DISABLE_COLLECTSTATIC = 0
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"books.apps.BooksConfig",
"debug_toolbar",
"corsheaders",
"django.contrib.postgres",
"django_celery_beat",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"corsheaders.middleware.CorsMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"debug_toolbar.middleware.DebugToolbarMiddleware",
"whitenoise.middleware.WhiteNoiseMiddleware",
]
ROOT_URLCONF = "search.urls"
LOGIN_REDIRECT_URL = "home"
LOGOUT_REDIRECT_URL = "home"
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
'http://localhost:8000',
'https://localhost:8000',
'http://0.0.0.0:8000',
'https://0.0.0.0:8000',
'http://127.0.0.1:8000',
'https://127.0.0.1:8000'
)
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / "templates"],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
STATIC_URL = "/static/"
If I access http://0.0.0.0:8000/admin/, the console says the following and the css does not load.
The Cross-Origin-Opener-Policy header has been ignored, because the URL's origin was untrustworthy. It was defined either in the final response or a redirect. Please deliver the response using the HTTPS protocol. You can also use the 'localhost' origin instead. See https://www.w3.org/TR/powerful-features/#potentially-trustworthy-origin and https://html.spec.whatwg.org/#the-cross-origin-opener-policy-header.

You may need to add SECURE_CROSS_ORIGIN_OPENER_POLICY = None to your settings file.
Also, check to see that your middleware is declared in the correct order according to the whitenoise and corsheaders docs. For example:
MIDDLEWARE = [
...
'django.middleware.security.SecurityMiddleware',
'corsheaders.middleware.CorsMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
...
]
The WhiteNoiseMiddleware doesn't look like it should be at the bottom of the list, according to their docs.

In your settings file:
Add like this to load static.
STATIC_URL = '/static/static/'
STATIC_ROOT = '/vol/web/static'

I don't know if this is the best answer but this is what I have after trying a lot of things.
I used https://stackoverflow.com/a/39291292
It finally worked

Related

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',
# ...
]

Django custom AppConfig breaks the project

I've got a bare-bones demonstration Django project created with Django 2.2. The structure looks like:
my_project/
├── db.sqlite3
├── my_app
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── models.py
│ ├── urls.py
│ └── views.py
├── manage.py
├── my_project
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── requirements.txt
This started as a tiny issue: "my_app" was showing up in the Django admin as "MY_APP" (with an underscore). The Django docs say that you can make this prettier by defining a custom app config that subclasses "django.apps.AppConfig", and that typically this subclass would be defined in (using my example) "my_app/apps.py". In fact, using manage.py startapp my_app even generates this for you:
# my_app/apps.py
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'my_app'
The docs also say to "put the dotted path to that subclass in INSTALLED_APPS". Another approach is to set the default_app_config variable in your app's "__init__.py", but that "New applications should avoid default_app_config. Instead they should require the dotted path to the appropriate AppConfig subclass to be configured explicitly in INSTALLED_APPS."
However, if I do add the path to the custom app config into INSTALLED_APPS like this:
# settings.py
...
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'my_app',
'my_app.apps.MyAppConfig'
]
...
the project immediately crashes with "LookupError: No installed app with label 'admin'."
The error traces back to the reference to admin.site.urls in the project's root "urls.py" (line 6 below):
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('my_app/', include('my_app.urls', namespace='my_app'))
]
In conclusion, adding the path to the "apps" module created by "startapp" -- even without
making any changes to that module -- crashes the project. OTOH if I go against the docs' advice and define default_app_config in "my_app/init.py", that does work.
This seems very basic, but Googling it is turning up nothing, which usually means I'm making some fundamental error that I don't realize. Any ideas, anyone?

Incorrect Django path to templates folder in settings.py

I am newly learning Django and was following the Learn Django 1.11 Tutorial.
Here is my current project tree:
├── manage.py
├── muypicky
│ ├── __init__.py
│ ├── old_settings.py
│ ├── settings
│ │ ├── base.py # Contains the settings (like shown in the tutorial)
│ │ ├── __init__.py
│ ├── urls.py
│ └── wsgi.py
├── requirements.txt
├── restaurants
└── templates # Templates Folder
└── index.html
I am trying to add the path to the tempelates folder in the settings folder. But the error shown
django.template.loaders.filesystem.Loader: .../muypicky/templates/index.html (Source does not exist)
Current setting.py file
TEMPLATES = [{
'DIRS': [os.path.join(BASE_DIR, 'templates')],
},]
Looking at the error, the file path is wrong because it goes into /muypicky/tempelates which is incorrect. So how do I get to root folder and then into tempelates folder with the given file tree in setting.py (base.py).
Any further queries, just ask and many thanks in anticipation.
Solution:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
and
TEMPLATES = [{'DIRS': [
os.path.join(BASE_DIR, 'templates')
],},]
Addition of os.path.dirname() was wrapped to go back one folder
settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
MEDIA_URL = '/uploads/'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [MEDIA_ROOT + '/'],#other app templates
'APP_DIRS': True,#heremention yourapp/templates
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.media'
],
},
},
]
also can you look at document djano template
I faced similar problem and was able to rectify with this:
TEMPLATES = [{
....
'DIRS': [os.path.join(BASE_DIR, '/templates')],
....
Dev Environment: django 2.2, python 3.6
so i think you need to add / before the 'templates' string...
I also think this changes with django versions as i'm currently working on another project that didn't require the trailing / before the 'templates' string on django 2.1, python 3.6. So i think this is worth trying out good luck

django module import error - python 2.7 vs python 3.4

I have installed django1.9 with python 2.7. But now I want to use it with python3.4. Hence I have modified symbolic link of python to python 3.4 like below.
sudo ln -s /usr/bin/python3.4 /usr/bin/python
Because same django works with python 2.7 and 3.4 as well so it should work. But now if I run ./mange.py runserver I am getting below error. But with Python 2.7 the same code works properly.
from Helpers import views
ImportError: No module named 'Helpers'
Please let me know whats wrong there? Below are the project structure.
myproject
├── myproject
│ ├── settings.py
│ ├── __init__.py
│ ├── urls.py
│ ├── wsgi.py
│ └─── Helpers
│ ├── views.py
│ └── __init__.py
└── manage.py
Urls.py is like below.
from django.conf.urls import url
from Helpers import views
urlpatterns = [
url(r'^$', views.index, name='index')
]
setting.py contains below relevant information.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myproject',
]
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Look for modules here as well.
sys.path.insert(0, os.path.join(BASE_DIR, "Helpers"))
Any idea?
Python 3 has changed the import policy. Take a look at this question.
Instead of adding Helpers directory to sys.path, add it's parent:
sys.path.insert(0, os.path.join(BASE_DIR, 'myproject'))
Or like #albar mentioned - use relative import:
from .Helpers import views

Django.staticfiles doesn't collect admin files

I noticed that staticfiles doesn't copy the admin's static files to STATIC_ROOT. I was under the impression (and I can't find references for that just now) that once you include django.contrib.staticfiles to your INSTALLED_APPS, it would automatically copy admin's static files (as well as all the other ones). However, it doesn't seem to be the case.
From browsing a dozen related questions on SO it seems that the accepted way is to include the hardcoded path to your virtualenv'd admin path to your NGINX, such as here:
location /static/admin {
root /webapps/hello_django/lib/python2.7/site-packages/django/contrib/admin/;
}
However, this seems rather dirty to me.
I should also mention that finders are working for me, i.e.
$ ./manage.py findstatic admin
Found 'admin' here:
/<path to venv>/lib/python2.7/site-packages/django/contrib/admin/static/admin
Am I missing something here?
Check if you have all settings set like that in your settings.py.
I suppose that your static files are under static dir in your project root folder.
import os
import sys
STATIC_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static/')
STATIC_URL = '/static/'
ADMIN_MEDIA_PREFIX = '/static/admin/'
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
INSTALLED_APPS = (
# default apps
'django.contrib.staticfiles',
# etc
)
STATICFILES_DIRS = ()
nginx config:
location /static {
alias /path_to_your_project/static;
access_log off;
expires max;
}
Turns out there was a subtle problem with my settings.py splitting method. For anyone coming here from Google, I was following deploydjango.com's and strategy on splitting settings.py, however ROOT_DIR was being defined in terms of the project, i.e. the following structure
$ tree -L 2
.
├── static
├── apps
└── project
├── __init__.py
├── settings
│   ├── __init__.py
│   ├── base.py
│   ├── dev.py
│   └── prod.py
├── urls.py
└── wsgi.py
with the following setting
STATICFILES_DIRS = (
ABS_PATH('apps', 'example_app', 'static'),
)
would result in ROOT_DIR being set to project/. And since ABS_PATH function defines paths based on ROOT_DIR, the apps/ folder is not visible (it should be preceded with '..').
The solution is of course to move apps/ folder inside the project/ folder, which makes sense. I.e. the correct structure is as follows:
$ tree -L 2
.
├── static
└── project_name
├── __init__.py
├── apps # <-- apps moved here
│   └── example_app
├── settings
│   ├── __init__.py
│   ├── base.py
│   ├── dev.py
│   └── prod.py
├── urls.py
└── wsgi.py
I realised this problem is very tied to the way I was doing things, however since this structure can be seen by some people as "best practice" (although some disagree), I hope this helps someone!