Static Files Versioning in Django

Installation

It is pretty easy in 2.2+, just add to your settings:

STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'

Don’t forget to set:

DEBUG = False

And do collectstatic. This way Django will run over all of your files and search for them in your statics directory.

ValueError: the file <file_path> could not be found

Be careful with urls – they might work on the website, but it the storage module may not identify the paths correctly. This error occurs:

ValueError: The file 'css/plugins/fonts/fontawesome-webfont.eot' could not be found with <django.contrib.staticfiles.storage.ManifestStaticFilesStorage object at 0x12ae4e220>.

Because it has a path like this

fonts/fontawesome-webfont.eot

You need to make it relative:

../../fonts/fontawesome-webfont.eot

RuntimeError: Max post-process passes exceeded.

If you see an error like this:

Post-processing 'All' failed!
RuntimeError: Max post-process passes exceeded.

Then check your @import statements – remove the commented once and try to find where the import is circular.

Conclusion

Versioning does not tolerate uncarefully made static files. You may spend a few hours removing rudimental imports, files, altering paths, removing urls to non-existent files. That’s totally normal.

Celery – schedule tasks with pauses between them

I needed to schedule 10 tasks that have these conditions

  1. A time gap between tasks is fixed (but varies)
  2. No need to pass results of one task to another
  3. Need to read a database in every task (important: at the moment of the execution)

I tried a few options, and this one worked

 ret = chain(task1.si(args).set(countdown=30*1), ..., task10.si(args).set(countdown=30*10)).apply_sync()

Important note – the signature here is not .s() but .si() this way you don’t pass the result of task1 to task2. You set the countdown with set() and not inside the apply_sync().

It is simple but it took me some time to figure out.

macOS (M1/M1 Pro) – ffmpeg with mp3 support and OpenCV

This is not funny – I spent a few evening fixing and fixing and fixing. Now ./configure then make and sudo make, but where is binary? Why is it not is /usr/bin/ OR /usr/local/bin/? Oh you do brew install opencv – but it does not work in terminal? Amazing. I was THIS close to wiping mac os and installing Linux on my macbook guys, THIS CLOSE.

Anyhow it is simple if you do the right thing.

ffmpeg with mp3 support

brew uninstall lame —force
brew uninstall homebrew-ffmpeg/ffmpeg/ffmpeg
brew install homebrew-ffmpeg/ffmpeg/ffmpeg —with-fdk-aac

In your virtualenv

pip uninstall ffmpeg
pip uninstall ffmpeg-python
pip install ffmpeg-python

And then install OpenCV (it is now working with pip):

pip install opencv-python

Moving Django to a subpath + Nginx + gunicorn (upd. 18.11.21)

upd. I forgot to include the most important line in the Nginx config. Sorry for that. but it does not work for me anymore. I am confused but I am postponing this for a few days to finish top priority tasks.

Super easy, super fun. Let’s base it on this great guide from Digital Ocean.

Say, the subpath you want is /secret/ 👀.

Add it to Nginx config:

server {
    listen 80;
    server_name server_domain_or_IP;

    location /secret/static/ {
        root /home/sammy/myprojectdir;
    }

    location /secret/ {
        rewrite /api(.*) $1 break;   # !!!!!!!!!!!!!! VERY IMPORTANT
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

Then, things we will change in settings.py:

  • in Nginx root means that in the directory it will look for a secret/static/ directory. But now you only have a regular static/.
  • Currently your Django generated static links are all example.com/static, we will change that too.

Your new settings variables will be something like this:

STATIC_URL = '/secret/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'secret/static/'

MEDIA_URL = '/secret/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'secret/media/'
FORCE_SCRIPT_NAME = 'secret'

That’s it. Go check all absolute paths that you wrote down in your project and you are good.

Make a JSON from PostgreSQL table (for Django)

First, choose a folder you want to copy the table to and grant postgres user access to it. I chose /home:

sudo chown -R postgres:postgres /home

Then log into postgres user:

sudo su - postgres

Then get to your database. If it is a Django project, you can find the name in settings.py:

psql dbname

Then, if you need your app’s tables, make a table name from these components:

{{ app_name }}_{{ model_name }}

For app userapp and model User, I have userapp_user. So in a /home/users.json I want to copy:

\t
\a
\o /home/users.json
SELECT row_to_json(r) FROM userapp_user AS r;

That’s it.

How to access Model’s pk/id when you create an instance in Django

If you need to modify instance fields depending on the instance’s pk or id, hop on.

When you create an instance, before it is saved, you can’t have pk or id as it is not yet created.

    def save(self, *args, **kwargs):
        # self.pk == None
        # self.id == None
        super().save(*args, **kwargs)
        # self.pk != None
        # self.id != None        

If you have a property that somehow depends on the value of self.pk or self.id and you want to have it saved on creating, you have two options.

Read More »