Separation of Static Files & Assets with Django Compressor & Usage of collectstatic - django

I'm having a really hard time getting my head around the use of django-compressor.
Here's what I'm attempting to accomplish:
Separation of Static Files & Assets (LESS, Coffeescript)
I would like to separate my LESS CSS and Coffeescript files into an assets directory
e.g.
app
└── assets
├── coffee
│ └── script.coffee
└── less
└── style.less
Leaving static assets such as images in my static directory
e.g.
app
└── static
├── hello.txt
└── photo.jpg
To do this, I've added the assets path to my STATICFILES_DIRS variable to allow django-compressor to find the files (which works as expected). Is this the correct approach? I have been trying to find an independent load path dedicated to django-compressor but didn't have any luck as I don't intend for these assets to be served as statics.
Collection of Files for Production Deployment
For deploying to production, I would then like the compiled CSS & JS files along with other media in my app/static directory (e.g. images and so on) to be collected to an app/static-prod directory. But this doesn't work out so well because the assets are also collected when using the collectstatic command.
e.g.
(django-cpython)fots#fotsies-ubprecise-01:~/django_learning$ ./manage.py collectstatic --noinput
Copying '/home/fots/django_learning/app/assets/less/style.less'
Copying '/home/fots/django_learning/app/assets/less/import.less'
Copying '/home/fots/django_learning/app/assets/coffee/script.coffee'
Copying '/home/fots/django_learning/app/static/photo.jpg'
Copying '/home/fots/django_learning/app/static/hello.txt'
5 static files copied.
Using the ./manage.py compress command only takes tare of my compiled files, not photo.jpg or hello.txt in this example.
The only possible way I've found to do this is using the --ignore flag with collectstatic
e.g.
(django-cpython)fots#fotsies-ubprecise-01:~/django_learning$ ./manage.py collectstatic --noinput --ignore=less --ignore=coffee
Copying '/home/fots/django_learning/app/static/photo.jpg'
Copying '/home/fots/django_learning/app/static/hello.txt'
2 static files copied.
I've also messed around with the COMPRESS_ROOT and COMPRESS_URL configuration variables but these only cause further trouble. Changing COMPRESS_ROOT resolves the collectstatic issue but now when using the compress command, the generated files end up in a different location to the static files.
These solutions hardly seem elegant. Is there a better way to do this? I feel like I'm missing something.
Thanks in advance for any help :)

I thought I'd provide the best solution I have found so far but please feel free to suggest better alternatives.
The biggest issue preventing my requirement is the fact that django-compressor uses the same path for its finder and output. The best solution I've found is as follows.
Creating a custom finder
We first create a custom finder based on a new setting I call COMPRESS_SOURCE_ROOT
from compressor.storage import CompressorFileStorage
from compressor.finders import CompressorFinder
from compressor.conf import settings
class CompressorFileAltStorage(CompressorFileStorage):
"""
This alternative django-compressor storage class is utilised
specifically for CompressorAltFinder which allows an independent
find path.
The default for ``location`` is ``COMPRESS_SOURCE_ROOT``.
"""
def __init__(self, location=None, base_url=None, *args, **kwargs):
if location is None:
location = settings.COMPRESS_SOURCE_ROOT
# The base_url is not used by the Finder class so it's irrelevant
base_url = None
super(CompressorFileAltStorage, self).__init__(location, base_url,
*args, **kwargs)
class CompressorAltFinder(CompressorFinder):
"""
A staticfiles finder that looks in COMPRESS_SOURCE_ROOT
for compressed files, to be used during development
with staticfiles development file server or during
deployment.
"""
storage = CompressorFileAltStorage
Using this new finder
Simply add this finder to your STATICFILES_FINDERS setting in addition to the usual 'compressor.finders.CompressorFinder'
e.g.
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
'mycomp.CompressorAltFinder',
'compressor.finders.CompressorFinder',
)
And now set up a new setting called COMPRESS_SOURCE_ROOT
e.g.
COMPRESS_SOURCE_ROOT = os.path.join(APP_DIR, 'assets')
I've also set my STATIC_ROOT too
STATIC_ROOT = os.path.join(APP_DIR, 'static-prod')
Testing the Solution in Development
I specifically tested my LESS source code compilation
(django-cpython)fots#fotsies-ubprecise-01:~/django_learning$ tree app/assets
app/assets
├── coffee
│ └── script.coffee
└── less
├── import.less
└── style.less
With template tags
{% compress css %}
<link rel="stylesheet" type="text/less"
href="{{ STATIC_URL }}less/style.less" />
{% endcompress %}
This is read from the assets directory successfully and updated when I change the files.
The output is placed in the static-prod directory:
(django-cpython)fots#fotsies-ubprecise-01:~/django_learning$ tree app/static-prod/
app/static-prod/
└── CACHE
├── css
│ ├── style.5abda32cfef7.css
│ └── style.6ca1a3d99280.css
└── js
└── script.8cb4f955df19.js
3 directories, 3 files
Testing the Solution for Production
For your reference, here's what my static directory looks like
(django-cpython)fots#fotsies-ubprecise-01:~/django_learning$ tree app/static
app/static
├── hello.txt
└── photo.jpg
0 directories, 2 files
So here we go
(django-cpython)fots#fotsies-ubprecise-01:~/django_learning$ rm -rf app/static-prod
(django-cpython)fots#fotsies-ubprecise-01:~/django_learning$ ./manage.py collectstatic --noinput
Copying '/home/fots/django_learning/app/static/photo.jpg'
Copying '/home/fots/django_learning/app/static/hello.txt'
2 static files copied.
(django-cpython)fots#fotsies-ubprecise-01:~/django_learning$ ./manage.py compress
Found 'compress' tags in:
/home/fots/django_learning/app/templates/layout.html
Compressing... done
Compressed 2 block(s) from 1 template(s).
(django-cpython)fots#fotsies-ubprecise-01:~/django_learning$ tree app/static-prod
app/static-prod
├── CACHE
│ ├── css
│ │ └── 5abda32cfef7.css
│ ├── js
│ │ └── 3b9d1c08d2c5.js
│ └── manifest.json
├── hello.txt
└── photo.jpg
3 directories, 5 files
I then ran the webserver as follows and confirmed that the site was operational
./manage.py runserver 0.0.0.0:8000 --insecure
Hope this helps somebody out there :)

Related

Django 3.1: Choice of static files directory

I have seen different ways in tutorials where the static files directory keep on changing.
1. Some put static files in the project root directory. Example
myproject
|__blog
| |__migrations
| |__static
| |__templates
mysite
|
static
|__blog
|__css
|__js
2. Some put the static files in the root directory of the app it is serving. Example
myproject
├── blog
│ ├── migrations
│ ├── static
│ └── templates
└── mysite
Where should static files be located?
It's whatever you want.
Personally, I prefer to keep my static resources at one place instead of scattered in different applications. Moreover, most staticfiles are needed in multiple apps, so I just put everything one place and serve from there.

how to use Hugo with github pages to automatically update content

I am using Hugo to deploy a static page to github pages
I have a git repo in the /public folder but the contents of the /static folder are not a part of the repository. Therfore they are not uploaded to the username.github.io page.
the /static folder contains images and css files. This is why my page does not look good after pushing to github.
My workaround is that each time I manually copy the /static folder into the /public folder after I build the site.
I think there should be a better solution and I am probably missing something in the config.toml file of the hugo workflow.
I am following the instructions from this site
Any ideas how to automatically include /static files into the repository?
Hugo copies all the files in the static/ directory into the public/ directory when your site is rendered. For example, if you have a static/ folder that looks like this:
.
├── css
│   └── main.css
└── img
├── favicon.png
└── avatar.png
Then when you build your site, the public/ folder will look like this:
.
├── css
│ ├── main.css
│ └── <theme css files>
├── img
│ ├── favicon.png
│ ├── avatar.png
│ └── <theme images>
<more content folders>
So the files in your static folder are probably being included already. The problem is likely to be that your theme is looking for your static files in the wrong place. Take a look at your theme documentation and see if it says anything about static assets.

Django 1.10 is not detecting changes in my models, and won't create migrations

I'm just getting started with Django. I like to hack at things, so alongside the polls tutorial I'm also building my own experimental application. It has come to pass that I want to change the name of the experimental application and its associated project.
In the course of working on that, I decided to drop my current database and start over fresh. Something went wrong, I can't remember what. It's been several hours now, making progress here, googling that there.
The situation I now seem to be in is that Django refuses to notice changes in my models.py. Currently, there are no migrations listed for the app when I run manage.py showmigrations, although the app is itself listed.
I have tried deleting the migrations directory, changing the contents of the models.py file, and combinations thereof, and also trying out various manage.py commands that looked promising. So far, nothing has worked.
So, what might I be doing wrong? Remember that I have changed the name of the app, which includes changing the name of directory it is stored in, as well as the name of the database. Search and replace has been performed on the files in the project and app. settings.py has been pored over, but everything I know about seems to match up fine.
Thanks!
I assume you have changed your app name in your settings.py? And when you say you changed your app name, did you start a new app or a new project... meaning, when you start you do this:
django-admin.py startproject myproject
Running startproject gives you the following folder and file structure:
├── manage.py
└── myproject
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
From there, you can run
python manage.py startapp myapp
This will make your folder structure look like this:
├── manage.py
├── my_django15_project
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── myapp
├── __init__.py
├── models.py
├── tests.py
└── views.py
From there, you could change your app by changing the folder name 'myapp' to 'mynewapp' and then by modifying your settings.py to have 'mynewapp' listed in your INSTALLED_APPS section.
After doing this you should run
pythonmanage.py makemigrations mynewapp
Verify that it makes the migration files
then run
python manage.py migrate
If you changed the folder myproject to a new name, such as mynewproject, I would suggest to try changing it's name back, then running
django-admin.py startproject mynewproject
then after you do that, update those files accordingly, and copy your myapp folder into the mynewproject folder.
Some other things you may want to check are that your database connectors are correct, and also try restarting your webserver.
If none of this works, you will need to give me some more information, so leave me a comment and let me know
Good Luck

Managing Static Files and Templates Django

I have gone through a few tutorials on creating a web application in Django. Based on the different tutorials so far, everyone seems to have a slightly different ways of storing their static files and templates.
In one particular tutorial, the author created a static folder at the same level as the project folder. Within the static folder, he created four more folders.They are :
media
static
static-only
templates
Within static, he created:
css
js
within templates, he stores all the web app templates such as base.html, aboutus.html, etc.
However, in the official django documentation, it says
https://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-during-development
Store your static files in a folder called static in your app. For example my_app/static/my_app/myimage.jpg.
May I ask which is the most common way of doing it? Many thanks!
It depends. Since my apps share the same set of static and templates I store them in root dirs:
# Settings
STATIC_URL = '/static/'
STATIC_ROOT = abspath('static')
STATICFILES_DIRS = (abspath('styles'),)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
...
)
TEMPLATE_DIRS = (abspath('templates'),)
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
# All styles are in one place
├── styles
│   ├── less
│   ├── js
# App's templates are stored in privite dirs so I can move them in app dir any time
# without changing my code: flatpages/flatpage_detail.html Also it works well with
# class based views.
├── templates
│   ├── base.html
│   ├── flaptages/
│   │   └── flatpage_detail.html
│   ├── another_app/
│   │   └── another_app_detail.html
Then I do manage.py collecstatic and have all static in root/static dir.
It fits me. But if I would make an app to share with community I will put static and templates in it's own dir as described in docs.

What good way for structure of project and owners of dirs in django?

Imagine that my django project contain few apps. On server it located at /var/www/ProjectName dir. My username is Foo and sometimes i want edit file of server. Which best solution for next questions?
What owner of /var/www?
What owner of /var/www/ProjectName?
What apache process owner?
Where locate static files (css, js)? Is it from all apps in one dir or different dirs for different apps? What Owner of this dir?
Where locate media files (with upload users)? Is it from all apps in one dir or different dirs for different apps? What Owner of this dir?
What owner of py and pyc files, dirs of apps?
PS. Maybe project is located at my home directory?
I have some suggestions about that, but I would like to hear more experienced people.
on ubuntu 12.04 root
drwxr-xr-x 3 root root 4096 Nov 8 11:59 www
cd /var/www && ls -la to see owner, probably root?
www-data, on 12.04 www-data homes directory is /var/www (www-data:x:33:33:www-data:/var/www)
you can collectstatic to whatever directory you want in your project. I often have a directory called static next to manage.py. The owner is probably the same as the owner of your django project. You only need to allow read access to this folder for apache
You will probably want to consider a centralized media folder, instead of having media for each app. For both static and media you can fairly easily upload everything to s3 using django-storages
the owner can be anyone you want, I can't say the owner because it is your machine. But, I think, the webserver will need to execute the py files, so you can change your permissions to allow for this.
You can locate the project whereever you want. In apache virtual host you give the location of your wsgi file. There is no reason your project must live in /var/www
Here is the structure I'm using.
django/
├── project_virtualenv (virtualenv folder)
└── versioned (folder for things that are versioned)
├── devdoc (documentation)
└── py (code)
└── project (django project)
├── django_app (django app)
│  
├── project (project folder)
   ├── files
   │   ├── media (media, user uploads, etc)
   │   ├── production_static (statics for production)
   │   └── static (statics for development)
   └── templates
  
The directory django is located in the home directory on the production server, only the wsgi.py is in the publicly available folder (in my case /home/user/public_html/wsgi.
I've chmoded everything in the Django folder to 777 just to get everything working on the testing production server. Not sure what are the security risks, even dough the files aren't directly served.