Eric
Eric

Reputation: 5331

How to make Django restart runserver on template change?

When I make a modification in a python source file in my project, Django detects that and restart runserver itself. But when I modify a django template, I have to kill runserver and restart it again : how can I do to have runserver restart automatically on template change ?

Upvotes: 40

Views: 22730

Answers (8)

user202729
user202729

Reputation: 3955

In newer Django versions:

The cached template loader is enabled by default, refer to https://docs.djangoproject.com/en/4.2/ref/templates/api/#django.template.Engine :

loaders is a list of template loader classes, specified as strings. Each Loader class knows how to import templates from a particular source. Optionally, a tuple can be used instead of a string. The first item in the tuple should be the Loader class name, subsequent items are passed to the Loader during initialization.

It defaults to a list containing:

  • 'django.template.loaders.filesystem.Loader'
  • 'django.template.loaders.app_directories.Loader' if and only if app_dirs is True.

These loaders are then wrapped in django.template.loaders.cached.Loader.

and:

Changed in Django 4.1: In older versions, the cached template loader was only enabled by default when DEBUG was False.

which means that even if DEBUG is True, the cached template loader is still used.

For reasons unknown to me, if ./manage.py runserver is used then the files are still read every time regardless of DEBUG value; while if gunicorn mysite.wsgi:application or ./manage.py runserver_plus is used then the files are cached as expected.

Anyway, following this answer in order to not wrap the loaders in cached.Loader always works. (you need to add the option to TEMPLATES.OPTIONS, which is passed to template.Engine -- remember to remove app_dirs if any)


Another alternative is to add to settings.py

INSTALLED_APPS = [
    'django_extensions',

then run for example

./manage.py runserver_plus  --extra-file polls/templates/polls/index.html

See https://django-extensions.readthedocs.io/en/latest/runserver_plus.html for documentation.

Upvotes: 4

TheRightChoyce
TheRightChoyce

Reputation: 3084

Another solution is to make sure you have debug set to true inside of you TEMPLATES config in settings.py

DEBUG = True

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['templates/'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
            'debug': DEBUG,
        },
    },
]

When debug is False you have to manually restart the server to see any changes made to templates (since they don't automatically trigger a restart)

Upvotes: 11

pX0r
pX0r

Reputation: 1560

You don't need to restart the server to reload the template changes.

In production you may do this:
In settings.py, for the TEMPLATES config
- Remove the APP_DIRS setting
- Instead, add this setting to OPTIONS:

'loaders': [
  'django.template.loaders.filesystem.Loader',
  'django.template.loaders.app_directories.Loader',
],

Why this works:
The DEBUG setting is True by default (in development mode). In this mode Django does not cache templates. But in production mode (i.e. DEBUG = False) Django enables template caching. Hence a server restart is needed to reload the edited/touched template.

Note:
Be mindful of the fact that - by disabling template caching, on your production machine, you will add an overhead for every request that goes through.

Upvotes: 3

Jopr
Jopr

Reputation: 330

The file will be read from disk without the need to restart runserver, just make sure you disable all caching.

Disable the Cached template loader

THe cached template loader is not enabled by default but you might have enabled this in you production settings. Make sure the cached template loader is not enabled your development settings. Django docs on the cached template loader

Use the dummy caching framework

When you are using the django caching framework this can cause the templates not to reload. The default framework Django uses is local-memory caching meaning you'll have to explicitly setup dummy caching to disable the caching framework. Django docs on dummy caching

Upvotes: 0

Luke Dupin
Luke Dupin

Reputation: 2305

I had a similar issue, however my templates required a django manager script to run in order to update them. There is no simple way to make django watch other file types, but here is a work around I use.

This is a standalone script I now use to run the dev server:

#!/usr/bin/python

import time, subprocess, sys, os, re
from threading import Thread

run = True

def monitor():
  while run:
    os.system("./manage.py update_templates")
    os.system("touch website/urls.py")
    os.system("inotifywait -e modify,create,delete website/templates/*.html")

t = Thread(target=monitor)
t.start()
time.sleep(0.5)

args = ''
if len(sys.argv) > 1:
  for i in range( 1, len(sys.argv)):
    args += sys.argv[i] +' '
print("./manage.py runserver %s" % args)
os.system("./manage.py runserver %s" % args)
run = False
t.join()

This script works under the following assumptions:

  1. Using python3
  2. This script is placed along side manager.py
  3. manager.py is runnable
  4. The web app is called website
  5. The website has a file called website/urls.py
  6. You're using GNU/Linux, which supports inotify

Upvotes: 1

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798626

Run touch against one of the Python source files.

Because runserver monitors .py files for changes, it does not restart for a change in the templates (.html). You can trigger this restart by virtually editing any of the .py files using the touch command, which refreshes its date modified and leaves all the other contents the same.

Upvotes: 10

Rabih Kodeih
Rabih Kodeih

Reputation: 9521

To add to knutin's answer, the problem you are facing is exactly caused by FetchFromCacheMiddleware so all what you need to do is to disable it in the settings.py file as follows:

settings.py:

MIDDLEWARE_CLASSES = (
    ...
    #'django.middleware.cache.FetchFromCacheMiddleware',
    ...
)

Upvotes: 6

knutin
knutin

Reputation: 5103

The file will by default be read from disk on every request, so there is no need to restart anything.

There is a caching template loader, but it is disabled by default. See the documentation for more info.

Upvotes: 23

Related Questions