[Fixed]-Django autoreload: add watched file

19👍

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.

6👍

Django >= 3.0

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)
👤Areeb

Leave a comment