Heroku django - messed up project structure - django

I've deployed my app on heroku (cedar stack) and all worked fine until a few days ago, When i noticed that my static files are not being served (appear with code 'canceled'). Next thing i noticed is that my project suddenly had new folders on same level as manage.py : admin/, css/, img/ and js/. I didnt create admin at all, using a buildin django admin site and didnt modify it in any way. I did create css, img and js folders under static/ inside my project, and its still there along with all its content. It's like all the folders in static/ got copied to manage.py level.
Running heroku run ls -l shows same changes on heroku. I suspect those changes cause troubles in serving static files.
heroku run python manage.py collectstatic --noinput
shows all files copied no problem.
my static dirs settings:
STATIC_ROOT = ''
STATIC_URL = '/static/'
STATICFILES_DIRS = (
# Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
os.path.join(os.path.dirname(__file__), 'static'),
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
I dont use S3 yet.
How to remove those files? What caused those dirs to appear?

When a Django application is deployed to Heroku, collectstatic is automatically run (Heroku docs). This collects all the static assets from your installed apps (including django.contrib.admin) and copies them to the STATIC_ROOT.
Check your STATIC_ROOT setting. It is probably not set correctly.
Here is a tutorial on using S3 with your static files.

Based on this post i learned that all this mess was caused by changing DEBUG to FALSE. Following Ohads' advice i checked my STATIC_ROOT setting, and as you can see, it wasn't set. Those are my fixed settings:
SETTINGS_PATH = os.path.abspath(os.path.dirname(__file__))
STATIC_ROOT = os.path.abspath(SETTINGS_PATH+'/static/')
STATIC_URL = '/static/'
STATICFILES_DIRS = ()
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
Adding:
if not settings.DEBUG:
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
)
in myapp/urls.py solved my problem.

Related

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 website giving trouble serving static files

I am working on a multi-app website. And I have bunch of noob questions.
My dir structure looks like as below:
/var/www/html/portal
src/
manage.py
portal/
static/
admin/
css/
img/
js/
fonts/
templates/
base.html
homepage.html
venv/
Is my dir structure as per as Django standards?
Are my STATIC files settings correct?
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
Or should it be
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')
Should I collectstatic after copying all my static files such as css,js etc or I can do it before copying files in those dirs?
If I do collectstatic without mentioning STATIC_ROOT I get an exception
django.core.exceptions.ImproperlyConfigured: You're using the staticfiles app without having set the STATIC_ROOT setting to a filesystem path.
But when I replace STATICFILES_DIRS with the following, my .css files stop serving. What am I doing wrong?
STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')
You don't need to run staticfiles when you're running a development server and DEBUG is set to True.
Static and media files can be then served directly via the web process (Docs) with adding these lines to your main urls.py:
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
As to the whole STATIC_URL, STATIC_ROOT, MEDIA_URL and MEDIA_ROOT, they're all related to how you'll serve your app in production, with a proper webserver.
What usually happens then is that the webserver (i.e. Nginx) handles serving files, not the Django app. But the Django app needs to know where are they. So:
STATIC_URL and MEDIA_URL need to be the same in your Django app settings and in your webserver config, for example with Nginx:
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
...
location /static {
alias /home/myusername/myproject/static/;
}
location /media {
alias /home/myusername/myproject/media/;
}
STATIC_ROOT MEDIA_ROOT are 100% about how you want to structure your project on the server. Assuming the above, you need to work out how to point it to /home/myusername/myproject/static/.
Example of my settings:
BASE_DIR = Path(__file__).parent.parent.parent
MEDIA_URL = '/media/'
MEDIA_ROOT = str(BASE_DIR.joinpath('media'))
STATIC_URL = '/static/'
STATIC_ROOT = str(BASE_DIR.joinpath('staticfiles'))
Media files will be directly uploaded to the MEDIA_ROOT, but notice that you need to somehow get the static files from your applications (which could be in a number of folders, a library you use can have some extra static files, Django Admin has then, etc.) to the folder that Nginx is pointed to (which should be the same as STATIC_ROOT). That's where collectstaticfiles comes in and copies all your static files to that directory.
In regards to directory structure, there are differences of opinion on how it should be set up. A quick google search can bring up some websites and discussions on Django project structures. I recommend reading some of the information to determine what is best for your and your project.
The Django documentation has a best practices page as well that is a good resource/reminder. Django Best Practices.
I mainly followed the Two Scoops of Django directory structure. The Two Scoops has helped me a lot in understanding this. My own twist looks something like this.
src/
app/
templates/
app_name/
base.html
other_pages.html
tests/
tests.py
app_files.py
static/
images/
css/
etc..
templates/
global_includes/
include_file.html
base.html
The collectstatic should not effect the serving of your static files during development. From what I have learned, collectstatic is more for when you are serving your static files during deployment from a separate server, or aws, heroku, etc. More info can be found here in the docs: Managing Static Files, staticfiles app, Deploying static files
I have learned that if my CSS files are not serving, it usually has something to do with my path. Chrome developer tools inspect element/console helps me with any path errors.
Have you added
+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
to your your main urlpattern/urls.py?
Here is more information on serving files during development: Serving static files during development.
Lastly check that your BASE_DIR is following the correct path for your project. You may have to change it.
I hope this helps.
Remember that if you have DEBUG set to 'False' it will ignore the staticfiles setting because it is expected that your webserver will be serving this directly. This caught me out a few times until I realized I hadn't updated the staticfiles folder (which I keep in a separate repository for reasons I can't remember now).
This seems to work in current django (2.2) :
from django.conf.urls.static import serve
urlpatterns += [
path(settings.STATIC_URL[1:], serve, {'document_root': settings.STATIC_ROOT })
]

django making deeper static root on every deploy

I have django setup to set the static root inside a static folder in the project directory, but every time I deploy it is adding another layer of root folders for the static files. I can't figure out why this is happenning...
+ project
-app1
+static
+root
+root
+root
+root
-templates
-manage.py
Here is the settings for static...
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static', 'root')
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
STATICFILES_DIRS = (
# Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
os.path.join(BASE_DIR, 'static'),
os.path.join(BASE_DIR, 'main', 'static')
)
AND NGINX...
# your Django project's static files - amend as required
location /static {
alias /home/django/langalang/static/root;
}
Your static root is included in your staticfiles_dirs, so every time Django runs collectstatic it puts it inside itself. Don't do that: keep them separate.

Configuring Django runserver to serve static files in a non-app directory?

I'm trying to configure Django to serve static files when using runserver (production works fine). Everything works fine for all of the static files that are under an apps directory. The problem comes with static files that are not under a specific app, but are in the final static directory. For instance, I have this project structure:
/myproject/
/myproject/static/
/myproject/static/css/foo.css
/myproject/app1
/myproject/app1/static/css/bar.css
urls.py
if settings.SERVE_STATIC:
urlpatterns += patterns('',
url(r'^static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.STATIC_ROOT}),
)
urlpatterns += staticfiles_urlpatterns() # one of these may be redundant.
settings.py
SERVE_STATIC = True
PROJECT_ROOT = '/myproject'
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(PROJECT_ROOT, 'static'),)
INSTALLED_APPS = ('app1',)
With these settings, I get the error:
ImproperlyConfigured: The STATICFILES_DIRS setting should not contain
the STATIC_ROOT setting
Which makes sense. I'm telling Django to collect static files, and put them in the same place - which could cause a loop.
If I comment out the STATICFILES_DIRS variable, django will find the static file 'bar.css'. But it does not find 'foo.css'.
If I comment out the STATIC_ROOT variable and put back the STATICFILES_DIRS, then it finds the file 'foo.css' - but of course, the 'collectstatic' command will no longer work.
Note - I realize that the '/static' directory is supposed to be empty, but the project I'm on, has files there anyway. :) As long as they're not overwritten by 'collectstatic', it looks like Django runserver should serve them - but it doesn't.
How do I serve the static files under STATIC_ROOT (such as foo.css) when running Django runserver?
Move the files that are in /static/ right now to a different directory -- call it /project-static/, for instance.
Then only include this line in urls.py:
urlpatterns += staticfiles_urlpatterns()
(remove the django.views.static.serve view)
And in settings.py, use this:
STATICFILES_DIRS = (os.path.join(PROJECT_ROOT, 'project-static'),)
Then you can put files in /project-static/ directory on your filesystem, the development server will serve them out of the /static/ URL prefix, and in production, collectstatic will find them and put them into the /static/ directory where the web server can find them.

Static file management in Django1.4

I've been confused with static files in Django for days. I found one solution that worked fine. But it collapsed when I set DEBUG=False. So I build up a new project and do some tests to get a clearer look.
First I create a project with the default settings. Then I changed some lines of the setting file into:
STATIC_ROOT = '%s/site_media' % PROJECT_DIR
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(STATIC_ROOT, 'images'),
)
After that, I put 'hi.jpg' at 'project_dir/images/hi.jpg'. I call runserver and visit 'http://127.0.0.1:8000/static/images/hi.jpg'. It doesn't work. What's the problem?
Here's how it works: when DEBUG=True then Django serves the static files itself. When DEBUG=False then Django won't do that anymore and you'll need to configure your web server to do it (such as Apache).
Django has a mechanism for that in django.contrib.staticfiles (see Managing static files and The staticfiles app). It basically means that you need to run the collectstaticmanagement command which will search for all static files in /static/ directories in your Django project and it will put them in one directory (STATIC_ROOT). When that has been done, your web server can serve the static files from that directory.
If one or more static files can't be found after running collectstatic then that means you have configured something incorrectly.
settings.py
PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
MEDIA_ROOT = os.path.join(PROJECT_DIR, 'site_media')
MEDIA_URL = '/site_media/'
STATIC_URL = '/static/'
if DEBUG:
STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')
else:
STATICFILES_DIRS = (
os.path.join(PROJECT_DIR, 'static'),
)
urls.py
if settings.DEBUG:
urlpatterns += patterns('',
url(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
)
:)
Django: Migrating from MEDIA_URL to STATIC_URL