Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django autoreload: add watched file

Tags:

python

django

When source files in my project change, django server reloads. I want to extend this to non-Python source files. I use native SQL queries, which are stored in separate files (eg. big_select.sql), and I want the server to reload when these files change.

I use django on Windows.

I have tried adding .py extension, which didn't work.

like image 690
kyrill Avatar asked Mar 20 '17 15:03

kyrill


Video Answer


2 Answers

Django>=2.2

The autoreloading was given a major overhaul (thanks to @Glenn who notified about the incoming changes in this comment!), so one doesn't have to use the undocumented Django features and append files to _cached_filenames anymore. Instead, register custom signal listener, listening to autoreloading start:

# apps.py
from django.apps import AppConfig
from django.utils.autoreload import autoreload_started


def my_watchdog(sender, **kwargs):
    sender.watch_file('/tmp/foo.bar')
    # to listen to multiple files, use watch_dir, e.g.
    # sender.watch_dir('/tmp/', '*.bar')


class EggsConfig(AppConfig):
    name = 'eggs'

    def ready(self):
        autoreload_started.connect(my_watchdog)

Django<2.2

Django stores the watched filepaths in the django.utils.autoreload._cached_filenames list, so adding to or removing items from it will force django to start or stop watching files.

As for your problem, this is the (kind of a hacky) solution. For the demo purpose, I adapted the apps.py so the file starts being watched right after django initializes, but feel free to put the code wherever you want to. First of all, create the file as django can watch only files that already exist:

$ touch /tmp/foo.bar

In your django app:

# apps.py
from django.apps import AppConfig
...
import django.utils.autoreload


class MyAppConfig(AppConfig):
    name = 'myapp'

    def ready(self):
        ...
        django.utils.autoreload._cached_filenames.append('/tmp/foo.bar')

Now start the server, in another console modify the watched file:

$ echo baz >> /tmp/foo.bar

The server should trigger an autoreload now.

like image 196
hoefling Avatar answered Oct 08 '22 18:10

hoefling


The accepted answer did not work in Django 3.0.7 probably due to changes since. Came up with the following after going through autoreload:

from django.utils.autoreload import autoreload_started

# Watch .conf files
def watch_extra_files(sender, *args, **kwargs):
    watch = sender.extra_files.add
    # List of file paths to watch
    watch_list = [
        FILE1,
        FILE2,
        FILE3,
        FILE4,
    ]
    for file in watch_list:
        if os.path.exists(file): # personal use case
            watch(Path(file))


autoreload_started.connect(watch_extra_files)
like image 39
Areeb Avatar answered Oct 08 '22 17:10

Areeb