I am trying to add a css file to my django application which I am deploying on openshift. Currently, I am able to have the css file work when running locally with debug and all that. However, when I deploy my application to openshift, the css file does not have any effect. Many of the other questions online seem to be referring to old versions of django and openshift (lots of references to a wsgi folder that doesn't seem to be standard anymore and triggering collectstatic manually)
My understanding with the current django/openshift relationship is that I do not need to do collecstatic manually as I am using the django-ex template from openshift, and during the build process the collectstatic command is run automatically, the ouput of which I can see in the logs. Notably, I can see that my style.css file for my application gets copied into STATIC_ROOT in that log.
My project structure from my project root is thus:
.
├── db.sqlite3
├── djangoWrapper
│ ├── __init__.py
│ ├── settings.py
│ ├── templates
│ │ └── djangoWrapper
│ │ └── index.html
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
├── gitlab-ci.yml
├── ldap
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── __init__.py
│ ├── migrations
│ ├── models.py
│ ├── static
│ │ └── ldap
│ │ └── style.css
│ ├── templates
│ │ └── ldap
│ │ ├── apiOffline.html
│ │ ├── index.html
│ │ ├── results.html
│ │ └── search.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── manage.py
├── openshift
├── README.md
├── requirements.txt
Here's what I am doing in my settings.py:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, "ldap", "static"),]
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
In my html files, I am then trying to load the css file with
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'ldap/style.css' %}">
in the <head> section.
I have attempted to do some debugging here because it would be assumed that the problem before I got to deployment was that my static files were not being put in the correct place/djgano couldn't find them. So I put some prints into my app and deployed it on openshift and got back the following info:
BASE_DIR: /opt/app-root/src
STATIC_ROOT: /opt/app-root/src/static
STATIC_URL: /static/
APP_VIEW_DIR: /opt/app-root/src/ldap/views.py
as well putting <p>"{%static 'ldap/style.css' %}"</p> into an html file, which displays as /static/ldap/style.css
From these tidbits, I know that the root directory for openshift is /opt/app-root/src/, that my static files are in /opt/app-root/src/static, and that my html is looking for the css file in /static/ldap/style.css. This seems like it should be working then as all of those directories line up. Is there something else about serving static files with django/openshift that I am missing here?
Finally got it working! I did use whitenoise, following the steps here.
Related
I've started a new Django project and run into issue at the very begining.
I have created a "core" app and inside I have prepared a simple html page using bootstrap.
Instead of using CDN I have downloaded bootstrap files and put it under static directory.
The problem is Django can't find those static files.
I am using the latest version of Django
>>> django.VERSION
(3, 2, 5, 'final', 0)
Snippet from my base.html file:
{% load static %}
<!-- Bootstrap core CSS -->
<link href="{% static 'assets/bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="{% static 'headers.css' %}" rel="stylesheet">
settings.py
STATIC_URL = '/static/'
STATICFILES_DIR = [
BASE_DIR / 'static'
]
and my directory structure:
.
├── apps
│ └── core
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── __init__.py
│ ├── models.py
│ ├── templates
│ │ └── core
│ │ ├── base.html
│ │ └── index.html
│ ├── tests.py
│ └── views.py
├── db.sqlite3
├── manage.py
├── ref_manager
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── static
│ ├── assets
│ │ └── bootstrap
│ │ ├── css
| | | ...
│ │ │ ├── bootstrap.css
│ │ │ ├── bootstrap.css.map
│ │ │ ├── bootstrap.min.css
│ │ │ ├── bootstrap.min.css.map
│ │ └── js
│ │ ├── bootstrap.bundle.js
│ │ ├── bootstrap.bundle.js.map
│ │ ├── bootstrap.bundle.min.js
│ │ ├── bootstrap.bundle.min.js.map
│ │ ├── bootstrap.esm.js
│ │ ├── bootstrap.esm.js.map
│ │ ├── bootstrap.esm.min.js
│ │ ├── bootstrap.esm.min.js.map
│ │ ├── bootstrap.js
│ │ ├── bootstrap.js.map
│ │ ├── bootstrap.min.js
│ │ └── bootstrap.min.js.map
│ └── headers.css
For your development environment, in 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)
You need staticfiles application in your settings:
INSTALLED_APPS = [
...
'django.contrib.staticfiles',
...
]
Set STATIC_URL, and STATICFILES_DIRS if you have static folder outside app directories.
This work fine in development mode:
python manage.py runserver
In operational environment, static files are copied into STATIC_ROOT by:
manage.py collectstatics
Then you can add to your urlpatterns
static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Static files will be served by django, but it is better to serve static files directly with your web server.
Try it in your settings.py file:
import os
STATIC_URL = "/static/"
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static")
]
Please fix indentation error, if any
In settings.py file change below code -
STATICFILES_DIRS = [
(BASE_DIR / "static"),
]
This works for me.
I am using Django Sites. I want to be able to have site-specific templates and static files.
My current directory structure is:
├── site_a
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
├── site_b
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
└── templates
├── site_a
│ ├── _navbar.html
│ ├── home.html
│ └── signup.html
└── site_b
├── _navbar.html
├── home.html
└── signup.html
I know that I can move templates inside the site_x directory if I declare it as an app in INSTALLED_APPS. Is there another way to tell Django to use templates in site_a/templates without declaring site_a as an app?
Also, I would also like to have site specific static files that are not placed in the project STATIC_ROOT so that my tree actually looks like:
.
├── site_a
│ ├── __init__.py
│ ├── settings.py
│ ├── static
│ │ ├── css
│ │ └── js
│ ├── templates
│ │ ├── _navbar.html
│ │ └── home.html
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
└── site_b
├── __init__.py
├── settings.py
├── static
│ ├── css
│ └── js
├── templates
│ ├── _navbar.html
│ └── home.html
├── urls.py
├── views.py
└── wsgi.py
You can setting static files via STATICFILES_DIRS (Django Docs) without declaring site_a:
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
('site_a', os.path.join(BASE_DIR, 'site_a/static')),
'Full path to your file or directory'
)
And in template:
<script src="{% static 'site_a/js/my_site_a.js' %}" type="text/javascript"></script>
And with declaring of your app:
Store your static files(Django Docs) in a folder called static in your app: site_a/static/site_a/example.jpg.
And for templates same: site_a/templates/site_a/example.html
in your settings.py set APP_DIRS:
TEMPLATES = [
{
...,
'APP_DIRS': True,
...
},
]
See Support for template engines and Overriding templates:
APP_DIRS tells whether the engine should look for templates inside installed applications. Each backend defines a conventional name for
the subdirectory inside applications where its templates should be
stored.
I have a django project for which suddenly (after updating PyCharm) the staticfiles can't be loaded anymore. This is the project structure:
├── _quanttool
│ ├── _quanttool
│ │ ├── __init__.py
│ │ ├── asgi.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ ├── _static
│ │ ├── css
│ │ ├── img
│ │ ├── js
│ │ ├── scss
│ │ └── vendor
│ ├── _templates
│ │ ├── base
│ │ ├── funds_tool
│ │ └── transaction_list
│ ├── funds_tool
.
.
.
│ ├── db.sqlite3
│ └── manage.py
├── venv
├── .gitignore
└── README.md
In the settings.py file i have configured:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = '/_static/'
STATIC_ROOT = '_static'
STATICFILES_LOCATION = [os.path.join(BASE_DIR, '_static')]
In the base HTML Template I have set {% load static %} and <link href="{% static 'css/sb-admin-2.min.css' %}" rel="stylesheet">
I really don't understand why I suddenly get the errors:
"GET /_static/css/sb-admin-2.css HTTP/1.1" 404 1682" ...
Any idea why Django can't find the staticfiles anymore?
Best
comment out STATIC_ROOT = '_static' and add the below code to your settings.py file.
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_URL = '/_static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, '_static'),)
If still not work then run this command on terminal
$ python manage.py collectstatic
I have my website. It is made using Django and deployed to Heroku.
And I used bootstrap3. Before deploying to heroku, when I test website at localhost:8000, bootstrap3 works well.
I used bootstrap3 source file, NOT CDN.
Below is my source tree.
/home/<path>/multichat$ tree
.
├── manage.py
├── static
│ ├── bootstrap-3.3.7-dist
│ │ ├── css
│ │ │ ├── bootstrap-theme.css
│ │ │ ├── bootstrap-theme.css.map
│ │ │ ├── bootstrap-theme.min.css
│ │ │ ├── bootstrap-theme.min.css.map
│ │ │ ├── bootstrap.css
│ │ │ ├── bootstrap.css.map
│ │ │ ├── bootstrap.min.css
│ │ │ └── bootstrap.min.css.map
│ │ ├── fonts
│ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ ├── glyphicons-halflings-regular.svg
│ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ ├── glyphicons-halflings-regular.woff
│ │ │ └── glyphicons-halflings-regular.woff2
│ │ └── js
│ │ ├── bootstrap.js
│ │ ├── bootstrap.min.js
│ │ └── npm.js
│ ├── css
│ │ └── base.css
│ └── js
│ └── jquery-1.12.2.min.js
├── staticfiles
│ └── default_profile.png
└── templates
├── 404.html
├── 500.html
├── base.html
├── home.html
└── index.html
All my html files extends templates/base.html.
To apply bootstrap3 I coded like this in base.html.
<!-- bootstrap -->
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}" type="text/css" />
<!-- Optional theme -->
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap-theme.min.css' %}" type="text/css" />
<!-- Latest compiled and minified JavaScript -->
<script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}" type="text/javascript"></script>
<!-- bootstrap end -->
It is my settings.py to manage staticfiles.
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
STATIC_ROOT=os.path.join(BASE_DIR, 'staticfiles')
After deploying to heroku, I access my website. Bootstrap3 is not applied. I modified base.html.
I removed href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}" and added CDN.
bootstrap3 is applied.
However I want to use bootstrap3 download file. I don't want to use CDN.
TO use bootstrap3 in production environment, what should I do?
Though it should work both way. But I will recommend to use Bootstrap CDN.
But if it is not working there, then just have a check where your static files are stored after running python manage.py collectstatic on production server and make changes accordingly.
And if downloaded bootstrap is not working now that means none of your css file will work coz your static files are stored somewhere else by python manage.py collectstatic. Hence it is not the problem of downloaded bootstrap or cdn.
I'm currently in the process of moving all of my static files to S3, as well as allowing some image uploads to my site. In general this is going fantastically. I got all of my existing css and js files up to S3 with no hassle, however I'm having some trouble with uploading images and saving them to S3.
Specifically this is how I'm handling file uploads within my view:
image_file = request.files["imageurl"]
if image_file and allowed_file(image_file.filename):
fn = "products/%s" % secure_filename(image_title + "." + image_file.filename.split(".")[-1])
image_file.save(url_for('static', filename=fn))
else:
response = app.make_response(render_template(
'admin/newImage.html',
title=title,
error="That Image file is invalid.")
)
return response
Which is all wrapping in a POST request handler. The problem here is that the url_for('static') fails to link to the correct path, and so I get an IOError anytime I try to save an image like this.
Normally I would assume I was just doing something silly with my directory structure, but the same pattern of url_for works perfectly for files in my static directory. Any ideas on how to remedy this? Here's my directory structure (trimmed down for viewing)
├── SpoolEngine
│ ├── admin.py
│ ├── __init__.py
│ ├── templates
│ │ ├── admin
│ │ │ ├── base.html
│ │ ├── base.html
│ │ ├── _forms.html
│ │ ├── posts
│ │ │ ├── complete.html
│ │ └── super_user
│ │ ├── base.html
│ ├── users.py
│ └── views.py
└── static
├── css
│ ├── admin.css
│ └── zebraTable.css
├── img
│ └── subtle_grunge.png
├── js
│ ├── compatibility.js
│ ├── list.js
│ ├── login.js
│ └── profiler.js
└── products
And for reference, url_for works perfectly within /static/css and links to the wrong url from admin.py Any ideas?
url_for returns an url path. Not a filesystem path.
So you're trying to save your file at /static/something which, for the system, means a path starting from the root of your filesystem, not your application path.
You can create the static path for your file with something like this
static_path_to_save = os.path.join([app.root_path, '/static', fn])
Just a side note, when dealing with uploads, remember to sanityze all the paths and to double check the destination. Best practices applies, like stripping slashes if you use the filename provided by the user (best is if you generate the filename).
In your code I see also a problem if 2 users uploads a file with the same name, overwriting each other. But this is probably safe in your context.