django collectstatic: How to keep the project structure? - python

Currently, collecstatic gathers all files of the project's Apps in one directory (STATIC_ROOT).
What should be done to keep the project structure for the static files:
STATIC_ROOT/App1
..
STATIC_ROOT/Appn
STATIC_ROOT/App3
thanks

The documentation recommends namespacing static files:
Static file namespacing
Now we might be able to get away with putting our static files directly in my_app/static/ (rather than creating another my_app subdirectory), but it would actually be a bad idea. Django will use the first static file it finds whose name matches, and if you had a static file with the same name in a different application, Django would be unable to distinguish between them. We need to be able to point Django at the right one, and the easiest way to ensure this is by namespacing them. That is, by putting those static files inside another directory named for the application itself.
Make sure to create an inner directory named after your app and put your files in there, e.g.
my_app/
static/
my_app/ ← This directory
file1
file1
...

Thank you chris,
I find exactly the solution as indicated here: How should I structure my static app files in Django?
I have just replace STATICDIR_FILES by :
STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]

Related

Changing the name of the sub folder inside Django Template path

I am new to Django and I have a path to my HTML file as
./templates/registration/login.html and I want to change it to
./templates/index/login.html
After renaming it to /templates/index/login.html, it is still picking up the old directory /templates/registration, could not find login.html screen and it throws an error.
Could someone tell me what changes we have to make in settings.py when we rename a folder name inside templates structure?
In your settings.py, you can define the templates location, which applies the template function per app.
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates')
)
I assume your app is named registration, hence why it is looking there. You can either rename your app or place all your templates in a global folder at the same level as the apps (and not within the apps themselves). The latter is not recommended for large applications.
Edit: Why is this labeled Python2? What version of Django is this?

Django Doesn't Serve STATIC_ROOT in DEBUG

I'm using Python 3.5 and Django 1.10 to run a development server:
./manage.py runserver 0.0.0.0:8000
In my settings.py I have:
DEBUG = True
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
And an app directory, with a static subdirectory for its static files:
proj/
proj/
...
app/
static/
a.txt
...
static/
b.txt
Pretty standard.
However: Django doesn't serve the STATIC_ROOT when DEBUG = True. It returns app/static/a.txt for /static/a.txt alright, but not static/b.txt for /static/b.txt.
Changing settings.py to read:
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
Works - but then I have to comment out STATIC_ROOT (otherwise Django complains it can't be in STATICFILES_DIRS).
Now, I can't just "use a different external static directory", e.g. static2, because I'm using django-sass-processor, which compiles .sass files into .css files, and puts these .css files in the STATIC_ROOT (which, as I've said, is inaccessible).
Things I've tried:
Settings up NGINX to serve that directory (like in a production environment). Works, but there just has to be another way.
Configuring django-sass-processor to write the .css files into said "different external static directory", e.g. static2, and including it in STATICFILES_DIRS. Again, works, but it just can't be that complicated!
Manually adding static files URLs in urls.py:
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
This one was quite a trip, so I thought I'd share it to save other people the trouble: it turns out that Django does that anyway, and actually overwrites my URLs - but it includes, as I've said, only my apps' static directories and those in STATICFILES_DIRS.
I even changed DEBUG to False and removed the if - but that didn't work as well, because then the django.conf.urls.static.static function actually returns an empty list. So, I implemented it myself using django.views.static.serve, and it finally worked, but again - it doesn't make sense I have to turn off debugging and manually implement serving static file.
Update
If you're working with django-sass-processor and running into similar problems, they've actually provided a solution I just noticed in their documentation: a special static finder you can add in your settings.py like so:
STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'sass_processor.finders.CssFinder',
]
(The first two are Django's default finders, so when you override this configuration you should include them manually).
But even now, for anything other than .css files, the STATIC_ROOT is actually the only static directory that is inaccessible via /static/, which I find pretty odd. So, I'd still like to solve (or at least understand...) it.
At first glance it seems very strange that Django doesn't serve files from STATIC_ROOT, but it makes sense when you consider the workflow Django intends for static files. Django expects that you bundle static files alongside apps and you save project-level static files in a separate directory that is checked into version control. Then, when you run manage.py collectstatic the STATICFILES_FINDERS are used to gather up all the files into a single directory (which should not be in version control) so they can be deployed to AWS S3 or whatever.
So the staticfiles finders have two jobs:
find a file via path, used for DEBUG mode static file serving
list all of the available files, used for collectstatic
If you were able to include STATIC_ROOT in your STATICFILES_DIRS then the collectstatic command would probably get stuck in a loop. Also, the Django developers don't intend for you to save files in STATIC_ROOT since it shouldn't be checked into version control.
However, there's times when you actually do want to serve files from STATIC_ROOT. In my case, I have a Celery task that creates thumbnails of uploaded images and saves them to the static files storage. In production that ends up saving on AWS S3 where it can be served.
So, if you have a valid use case for serving files from STATIC_ROOT just define your own file finder and add it's path to STATICFILES_FINDERS:
from django.contrib.staticfiles.finders import BaseFinder
from django.contrib.staticfiles.storage import staticfiles_storage
class StaticRootFinder(BaseFinder):
"""
For debug mode only. Serves files from STATIC_ROOT.
"""
def find(self, path, all=False):
full_path = staticfiles_storage.path(path)
if staticfiles_storage.exists(full_path):
return [full_path] if all else full_path
return []
def list(self, ignore_patterns):
return iter(())

How to handle assets (css, js, etc) with Django?

I'm new to Django and to Python, and I've just completed Django's "build your first app" tutorial. I found it fantastic. However it never spoke about stylesheets, javascripts or anything of the like.
Where should they go? Currently my project directory looks like this:
myproject
+app1
+app2
+myproject
+public
+css
+img
+js
+templates
Am I doing it correctly? I would like to stick to Django/Python standards as much as possible. Also, if I would like to include certain styles and scripts in all of my templates, how can I do that? Let's say I'm using Bootstrap.
You should probably take a closer look at Managing static files.
Basically you can put a static folder in each of your apps (similar to your template folders) and the more general stuff (base.css, project-wide icons, jquery-plugins) in a static folder in your project root.
So the layout might look like this:
myproject
+app1
+static
+app1
+css
+js
+app2
+static
+css
+img
Once you deploy your project you can use, the collectstatic-command from contrib.staticfiles to collect all your static files to a single directory (STATIC_ROOT) where you can serve it from.
I prefer to call the +public folder +static, and put the +template (app specific) folder inside the application that is using them (so to avoid confusion and to be able to use a template with a different name twice), also I don't understand why you put +myproject inside your root project.

Where to put templates in Django 1.4?

I got a bit confused, because when I use the generic ListView class, Django is looking for "appname/objectname_list.html" inside the "appname/templates" folder. This results in:
appname/templates/appname/objectname_list.html
If I supply "template_name", it does not require the subfolder inside the templates folder anymore.
Why doesn't it find the objectname_list.html inside the "templates" folder like before in 1.3 ? Did I configure something wrong or did they change the place where I'm supposed to put my templates as well ? In 1.3 I used to place template html files inside "appname/templates" directly instead of using a subfolder.
For me it does not make sense to use another subfolder with the name of the app, where the templates folder is already in. Or am I missing something useful ?
I could not find anything about it in the release notes.
I don't think this is 1.4 specific. If you will want your template in a subfolder, specify template_name = 'subfolde/template.html'
Regarding template dirs, from the docs:
... For each app in
INSTALLED_APPS, the loader looks for a templates subdirectory. If the
directory exists, Django looks for templates in there.
So the actual dir is:
projectname/appname/templates/appname/objectname_list.html
^^^ ^^^
This helps you keep everything inside the app folder and does not require you to configure anything,
This also means that if you have apps foo, bar and baz, you can still have one templates dir under one of the apps:
myproj/foo/templates/foo/...
myproj/foo/templates/bar/...
myproj/foo/templates/baz/...

Why absolute paths to templates and css in django ? (Isn't that a bad practice ?)

In django, the documentation asks to use the absolute paths and not the relative paths.
Then, how do they manage portability ?
If I have my template in the project folder then, even a rename of the folder will cause breakage.. !
Then what is the reason behind this practice ?
Please explain ?
Could you post a link to that piece of documentation, please?
In Django you configure, in settings.py, the search path for templates (through TEMPLATE_DIRS variable). Then, inside a view, you render a template naming its file relative to one of the path included in TEMPLATE_DIRS. That way, whenever you move you template dir you just need to modify your settings.py
As for static files, like CSS docs, Django does not need to know anything about them (unless you are serving static files through django itself, which is discouraged by django's documentation): you only need to tell your web server where to find them.
I switch environments from a Linux desktop to a Windows laptop, so hard coding paths won't work for me either.
There may be a better way to do this, but I wrote this function that goes at the top of my settings.py to get the absolute path from a relative path in my project:
#settings.py
import os
def map_path(directory_name):
return os.path.join(os.path.dirname(__file__), \
directory_name).replace('\\', '/')
That allows me to do:
MEDIA_ROOT = map_path('static')
TEMPLATE_DIRS = (
map_path('templates'),
)
"static" and "templates" live under my project root. Hope that helps you out.

Categories

Resources