Automatically reload your browser in development.

Overview

django-browser-reload

https://img.shields.io/github/workflow/status/adamchainz/django-browser-reload/CI/main?style=for-the-badge https://img.shields.io/badge/Coverage-100%25-success?style=for-the-badge https://img.shields.io/pypi/v/django-browser-reload.svg?style=for-the-badge https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge pre-commit

Automatically reload your browser in development.

Requirements

Python 3.6 to 3.10 supported.

Django 2.2 to 4.0 supported.


Are your tests slow? Check out my book Speed Up Your Django Tests which covers loads of best practices so you can write faster, more accurate tests.


Installation

  1. Install with pip:

    python -m pip install django-browser-reload
  2. Ensure you have "django.contrib.staticfiles" in your INSTALLED_APPS.

  3. Add django-browser-reload to your INSTALLED_APPS:

    INSTALLED_APPS = [
        ...,
        "django_browser_reload",
        ...,
    ]
  4. Include the app URL’s in your root URLconf(s):

    from django.urls import include, path
    
    urlpatterns = [
        ...,
        path("__reload__/", include("django_browser_reload.urls")),
    ]

    You can use another prefix if required.

  5. Add the template tag to your base template. This can go anywhere, but it’s best just before </body>:

    {% load django_browser_reload %}
    
    ...
    
        {% django_browser_reload_script %}
      </body>
    </html>

    To add django-browser-reload to Django’s admin, do so in a template called admin/base_site.html:

    {% extends "admin/base_site.html" %}
    
    {% load django_browser_reload %}
    
    {% block extrahead %}
        {{ block.super }}
        {% django_browser_reload_script %}
    {% endblock %}

    This follows Django’s documentation on extending an overriden template.

All done! 📯

For faster and more efficient reloading, also set up Django’s built-in Watchman support.

What It Does

When DEBUG is True, the template tag includes a small script. This script connects back to the development server and will automatically reload when runserver restarts, or a template is modified. (Template modification detection requires Django 3.2+.) The reload only happens in the most recently opened tab.

Example App

See the example app in the example/ directory of the GitHub repository. Start it up, and try modifying example/core/views.py or templates/index.html to see the reloading in action.

How It Works

Here’s a diagram:

                                     Browser

                             Tab 1    Tab 2     Tab N
                           listener  listener  listener
                                \       |       /
  Django                         \      |      /
                                  \     |     /
Events View --------------------> Shared worker

The template tag includes a listener script on each page. This listener script starts or connects to a SharedWorker, running a worker script. The worker script then connects to the events view in Django, using an EventSource to receive server-sent events.

This event source uses StreamingHttpResponse to send events to the worker. The view continues streaming events indefinitely, until disconnected. (This requires a thread and will not work if you use runserver’s --nothreading option.)

On a relevant event, the worker will reload the most recently connected tab. (It avoids reloading all tabs since that could be expensive.)

To reload when a template changes, django-browser-reload piggybacks on Django’s autoreloading infrastructure. An internal Django signal indicates when a template file has changed. The events view receives this signal and sends an event to the worker, which triggers a reload. There is no smart filtering - if any template file changes, the view is reloaded.

To reload when the server restarts, django-browser-reload uses a version ID. This ID is randomly generated when the view module is imported, so it will be different every time the server starts. When the server restarts, the worker’s EventSource reconnects with minimal delay. On connection, the events view sends the version ID, which the worker sees as different, so it triggers a reload.

The events view also sends the version ID every second to keep the connection alive.

Compatibility

EventSource is highly compatible. SharedWorker is a bit less so, but should work with Chrome, Edge, Firefox, and Opera.

Comments
  • Browser not reloading

    Browser not reloading

    Python Version

    3.9.10

    Django Version

    4.0.2

    Package Version

    1.3.0

    Description

    Did an update on django-tailwind from 2.x to 3.1.1 and also changed from browser-sync to django-browser-reload. Followed the update instructions and compared all steps to a previously updated project without any problems.

    But this time the browser just does not reload on changes. The script-Tag is in the source code of the page. Tailwind start does recognize the updated html or css. But the browser does not reload. No GET request to update the site is fired.

    Do you have any idea where I can look for the problem?

    opened by datencoach 25
  • Implement a check that the development server is back before reloading a page

    Implement a check that the development server is back before reloading a page

    Description

    Hi Adam,

    I'm trying to get django-browser-reload work with Tailwind CSS, and I'm almost there. However, I noticed a weird lag happening sporadically after I edit HTML code - the page reloads and shows the "No server response" and then reloads again and shows the working page. I guess that's because the reloader tries to fetch a page while the Django server is restarting. Please see the attached video. The behavior I'm describing happened in the second part.

    2022-01-09_23-24-07 (1)

    So I was wondering if it's possible to implement a check that the development server is back before reloading a page?

    PS: Thanks for the package!

    opened by timonweb 12
  • want a docs pull-request for an 'autohotkey' Windows alternative?

    want a docs pull-request for an 'autohotkey' Windows alternative?

    Python Version

    No response

    Django Version

    No response

    Package Version

    No response

    Description

    Hi Adam,

    I'm using the below with AutoHotKey to quickly refresh my browser via a hotkey. It's Windows specific though (although I bet there's alternatives for Mac and Linux).

    I find it useful to refresh only at key moments, which this solution offers.

    Happy to add a section to your docs if you want, on this solution. Or if you'd prefer, I could just flesh this solution out in a blog, and just reference that. No probs if you feel this is not a good idea :)

    Cheers, Andy.

    F2::
    ; Save current window
    WinActivate,ahk_class Chrome_WidgetWin_1
    
    ; ---------------------------------------
    
    ; Refresh Chrome
    Process, Exist, chrome.exe
        If(ErrorLevel) {
            WinActivate, ahk_pid %ErrorLevel%
            Send {F5}
        }
    
    ; ---------------------------------------
    
    opened by andytwoods 6
  • Debounce reload events

    Debounce reload events

    For some reason I sometimes see multiple reload events in the example app, for saving a template once. Possibly there’s something in the way watchman watches the project + example app that causes extra events.

    This PR fixes that by “debouncing” - starting a 50ms timer when we see a change, and restarting it out every time we get another change. This is a good idea anyway as it will help workflows where multiple files change in quick succession, e.g. when running Tailwind and changing HTML that triggers a CSS change.

    opened by adamchainz 4
  • Browser not reloading

    Browser not reloading

    Python Version

    3.10.6

    Django Version

    4.1.2

    Package Version

    1.6.0

    Browser

    Chrome, Firefox, Safari

    Description

    Dear Adam, it is me again (https://github.com/adamchainz/django-browser-reload/issues/68). Sorry to open this issue again, but I wanted to let you know that me problem is back.

    When I startet a new project everything worked fine. Until now. I did not work on this project for a few weeks and when I now updated wagtail, django and django-tailwind I noticed that the reload stopped working again.

    I spend serval hours debugging yesterday, but was not able to find the problem. But I figured out that the route "/reload/events/" seems to be the problem. Not exactly the route as the url and view are working and send a 200 http-code, but no pings are sent.

    Broken project (same picture on url 127.0.0.1:8000): image

    Working project: image

    Do you have any ideas what could prevent that the ping events are send? I can see them on views.py, but they do not arrive at the browser.

    I totally understand if you close this straight away as we already spent time on this not finding an answer.

    Thanks and beste Regards, Thomas

    opened by datencoach 3
  • Not reloading when changing template files (.html) but reloading when changing PY files (DEBUG)

    Not reloading when changing template files (.html) but reloading when changing PY files (DEBUG)

    Python Version

    3.10

    Django Version

    4.1

    Package Version

    1.6.0

    Browser

    EDGE 103.0.1264.77 (Official build) (64-bit)

    Description

    When I change .py files, the reload works as expected. But when I change html template files, inside the template folder of an app, or any other place, the reload is not triggered. Neither is the runserver reload, so it might have to do something with Django. But if there is a fix to make it work, every time we change HTML templates, it would be great. I am using jinja2 templates, and I made sure that the reload code is injected (but not that that could be the issue, because the reload is triggered, as I said, when .py files are changed). I tried several things inside DJANGO, but none of them worked.

    Thanks a lot,

    opened by martinlombana 3
  • Auto-refresh KO when updating view

    Auto-refresh KO when updating view

    Python Version

    3.10.4

    Django Version

    4.0

    Package Version

    1.3.0

    Description

    (EDITED)

    I carefully installed django-browser-reload and it has some unexpected behaviour with my project. I decided to build your example project to find the issue, and the problem is the same within it.

    Everything works as expected when I change and save a template file, I can see the changes occur in the browser.

    But when I'm working with a view file, the server is actually reloaded when I save the file (which is something I expect):

    /workspaces/dbr/example/core/views.py changed, reloading.
    Watching for file changes with StatReloader
    Performing system checks...
    
    System check identified no issues (0 silenced).
    May 05, 2022 - 09:21:44
    Django version 3.2.13, using settings 'example.settings'
    Starting development server at http://127.0.0.1:8001/
    Quit the server with CONTROL-C.
    

    However, django-browser-reload seems to do nothing at this time, hence I see no change in my browser. Plus, once the server restarted, the hot-reloading does not work on templates too. I need to refresh my browser manually in that case to see the changes made in python files, and make the hot-reloading work again.

    Using your example project, changing a thing in a view such as "title": "My Awesome Site" and then saving, will do nothing.

    Maybe a package upgrade broke something.

    $ pip freeze
    
    asgiref==3.4.1
    Django==4.0.1
    django-browser-reload==1.3.0
    Jinja2==3.0.3
    MarkupSafe==2.0.1
    pywatchman==1.4.1
    sqlparse==0.4.2
    

    Thanks for your time.

    opened by ddahan 3
  • Marking middleware as unused when not in DEBUG

    Marking middleware as unused when not in DEBUG

    Description

    Hi, I read in Django documentation that there's a way to mark a middleware as unused at startup. And it is completelly skipped by Django. I'm refering to [https://docs.djangoproject.com/en/4.0/topics/http/middleware/#marking-middleware-as-unused](this entry in the doc). Maybe this would be useful here when DEBUG=False ? Thanks for this project.

    opened by cpaquot 3
  • Depends on Jinja2?

    Depends on Jinja2?

    Python Version

    3.9.5

    Django Version

    4.0

    Package Version

    main

    Description

    Hey Adam, Saw this on your blog (via the Django subreddit) and came here to see how you'd ended up doing things - mostly to see how you'd solved some of the thorny issues related to cancelling the SSE's WSGI request on client hang-up (because I have a similar package and I had to do some hacks!) ... and actually I don't know how in the world you've done it, but done it you have, kudos (I'd love to know which bit is solving it, if you're feeling generous at any point)

    Anyway, trying to set it up to explore the hang-up situation, I encountered the following exception:

    File "/path/.direnv/python-3.9.5/lib/python3.9/site-packages/django/utils/autoreload.py", line 644, in run_with_reloader
        start_django(reloader, main_func, *args, **kwargs)
      File "/path/.direnv/python-3.9.5/lib/python3.9/site-packages/django/utils/autoreload.py", line 629, in start_django
        reloader.run(django_main_thread)
      File "/path/.direnv/python-3.9.5/lib/python3.9/site-packages/django/utils/autoreload.py", line 334, in run
        autoreload_started.send(sender=self)
      File "/path/.direnv/python-3.9.5/lib/python3.9/site-packages/django/dispatch/dispatcher.py", line 170, in send
        return [
      File "/path/.direnv/python-3.9.5/lib/python3.9/site-packages/django/dispatch/dispatcher.py", line 171, in <listcomp>
        (receiver, receiver(signal=self, sender=sender, **named))
      File "/path/.direnv/python-3.9.5/src/django-browser-reload/src/django_browser_reload/views.py", line 62, in on_autoreload_started
        for directory in jinja_template_directories():
      File "/path/.direnv/python-3.9.5/src/django-browser-reload/src/django_browser_reload/views.py", line 41, in jinja_template_directories
        from django.template.backends.jinja2 import Jinja2
      File "/path/.direnv/python-3.9.5/lib/python3.9/site-packages/django/template/backends/jinja2.py", line 3, in <module>
          import jinja2
    ModuleNotFoundError: No module named 'jinja2'
    

    Naturally it's easy enough to resolve (installed jinja2), but thought you might want to know.

    opened by kezabelle 3
  • reload event never received when django is behind the reverse proxy

    reload event never received when django is behind the reverse proxy

    Python Version

    3.10

    Django Version

    4.1.2

    Package Version

    1.6.0

    Browser

    Chrome

    Description

    I use django as front service and my back-end service container in the same container stack. I have to manage sub path based routing, so I decided to use nginx as a reverse proxy.

    But when I change and save template code, The browser never received reload event from server. (and browser just reloaded when the worker long polling was timed out.)

    here's my nginx.conf

    worker_processes 4;
    
    events {
        worker_connections 1024;
    }
    
    http {
        server {
            listen 80;
            server_name localhost;
    
            location /api/web {
                return 302 /api/web/;
            }
            location /api/web/ {
                proxy_pass http://web:8000/;
            }
    
            location / {
                proxy_pass http://front:80/;
            }
        }
    }
    

    Hope that I can get the solution. thank you! :)

    opened by E5presso 2
  • SSL Error when using Django extenions' runserver_plus

    SSL Error when using Django extenions' runserver_plus

    Python Version

    3.10.8

    Django Version

    4.1.3

    Package Version

    No response

    Browser

    Chromium: Version 107.0.5304.87 (Official Build) Arch Linux (64-bit)

    Description

    Hi Adam,

    Thanks for this awesome and helpful tool.

    A problem come when I use it with the runserver_plus:

    python manage.py runserver_plus localhost:8000 --cert-file certs/localhost.crt --key-file certs/localhost.key --nostatic --settings=config.settings.dev
    

    It shows:

    127.0.0.1 - - [03/Nov/2022 13:18:13] "GET /static/debug_toolbar/js/utils.js HTTP/1.1" 304 -
    Error on request:
    Traceback (most recent call last):
      File "/home/me/.local/share/virtualenvs/django-starter-xnFyc4Yx/lib/python3.10/site-packages/werkzeug/serving.py", line 335, in run_wsgi
        execute(self.server.app)
      File "/home/me/.local/share/virtualenvs/django-starter-xnFyc4Yx/lib/python3.10/site-packages/werkzeug/serving.py", line 325, in execute
        write(data)
      File "/home/me/.local/share/virtualenvs/django-starter-xnFyc4Yx/lib/python3.10/site-packages/werkzeug/serving.py", line 298, in write
        self.wfile.write(b"\r\n")
      File "/usr/lib/python3.10/socketserver.py", line 826, in write
        self._sock.sendall(b)
      File "/usr/lib/python3.10/ssl.py", line 1237, in sendall
        v = self.send(byte_view[count:])
      File "/usr/lib/python3.10/ssl.py", line 1206, in send
        return self._sslobj.write(data)
    ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:2396)
    

    When I remove the django_browser_reload from the INSTALLED_APPS, the problem disappear.


    Django version: 4.1.3 Python version: 3.10.8 (main, Oct 13 2022, 21:13:48) [GCC 12.2.0] [x86_64-Linux-5.15.76-1-MANJARO]

    opened by a14d 1
  • Doesn't work with ASGI

    Doesn't work with ASGI

    Description

    Hi,

    I'll start by saying this project is wonderful but if for some reason you accidentally run this in production you'll end up with a completely broken asgi event loop. The browser reload code seems to hog the event loop even after a request is closed. For synchronous servers it seems to be less of an issue but with the asgi

    The logs will show the following

    socket.send() raised exception
    

    and then the worker will timeout after hanging for 10-15 seconds. It would be great to have either a warning if the browser middleware is running or maybe detect if we're using the none dev server and throw a warning that it may block the event loop

    There may also be an additional problem where socket connections arent properly being closed after a page is refreshed?

    opened by califlower 4
  • Broadcast events

    Broadcast events

    Description

    Within a single browser, the SharedWorker only refreshes the latest opened tab. That's a good feature, it prevents a thundering herd.

    But if you open several browsers or use isolated sessions within one browser, several SharedWorkers will run and connect to the events view. But unfortunately the threading event will mean only one of these running events views will actually pass the reload message to one of the browsers.

    It would be good to use some kind of thread messaging construct to pass the event to all relevant running threads from event views. Thus, one might open a couple browsers to check between their incompatibilities, and see them all reload.

    opened by adamchainz 0
  • Restore scroll position, form state, and focus

    Restore scroll position, form state, and focus

    Description

    @kezabelle's django-livereloadish does this by restoring these key pieces of state after reload. It serializes the values into sessionStorage and restores them on page load.

    I think this behaviour would be valuable to add here. Probably a good idea to add one at a time.

    opened by adamchainz 1
  • Note/deal with caching

    Note/deal with caching

    Description

    The browser will cache static assets so they may not update for users. There's no easy way aorund this in JS that I can see, but users can open devtools and disable caching.

    location.reload() can maybe do a hard reload on Firefox: https://twitter.com/AdamChainz/status/1471150134503346182

    At least we could mention to open devtools.

    opened by adamchainz 1
  • Prevent multiple reloads

    Prevent multiple reloads

    On my DB Buddy project I'm seeing many reloads for a single file changes. It looks like watchman is signalling the same file changing repeatedly.

    Maybe something needs changing in this project, or we need to add debounce logic.

    opened by adamchainz 0
Owner
Adam Johnson
🦄 @django technical board member 🇬🇧 @djangolondon co-organizer ✍ AWS/Django/Python Author and Consultant
Adam Johnson
Duckiter will Automatically dockerize your Django projects.

Duckiter Duckiter will Automatically dockerize your Django projects. Requirements : - python version : python version 3.6 or upper version - OS :

soroush safari 23 Sep 16, 2021
A calendaring app for Django. It is now stable, Please feel free to use it now. Active development has been taken over by bartekgorny.

Django-schedule A calendaring/scheduling application, featuring: one-time and recurring events calendar exceptions (occurrences changed or cancelled)

Tony Hauber 814 Dec 26, 2022
A simple demonstration of how a django-based website can be set up for local development with microk8s

Django with MicroK8s Start Building Your Project This project provides a Django web app running as a single node Kubernetes cluster in microk8s. It is

Noah Jacobson 19 Oct 22, 2022
Basic Form Web Development using Python, Django and CSS

thebookrain Basic Form Web Development using Python, Django and CSS This is a basic project that contains two forms - borrow and donate. The form data

Ananya Dhulipala 1 Nov 27, 2021
Automatically deletes old file for FileField and ImageField. It also deletes files on models instance deletion.

Django Cleanup Features The django-cleanup app automatically deletes files for FileField, ImageField and subclasses. When a FileField's value is chang

Ilya Shalyapin 838 Dec 30, 2022
A tool to automatically fix Django deprecations.

A tool to help upgrade Django projects to newer version of the framework by automatically fixing deprecations. The problem When maintaining a Django s

Bruno Alla 155 Dec 14, 2022
Get inside your stronghold and make all your Django views default login_required

Stronghold Get inside your stronghold and make all your Django views default login_required Stronghold is a very small and easy to use django app that

Mike Grouchy 384 Nov 23, 2022
DCM is a set of tools that helps you to keep your data in your Django Models consistent.

Django Consistency Model DCM is a set of tools that helps you to keep your data in your Django Models consistent. Motivation You have a lot of legacy

Occipital 59 Dec 21, 2022
System checks for your project's environment.

django-version-checks System checks for your project's environment. Requirements Python 3.6 to 3.9 supported. Django 2.2 to 3.2 supported. Are your te

Adam Johnson 33 Dec 22, 2022
A fresh approach to autocomplete implementations, specially for Django. Status: v3 stable, 2.x.x stable, 1.x.x deprecated. Please DO regularely ping us with your link at #yourlabs IRC channel

Features Python 2.7, 3.4, Django 2.0+ support (Django 1.11 (LTS), is supported until django-autocomplete-light-3.2.10), Django (multiple) choice suppo

YourLabs 1.7k Jan 1, 2023
Django-environ allows you to utilize 12factor inspired environment variables to configure your Django application.

Django-environ django-environ allows you to use Twelve-factor methodology to configure your Django application with environment variables. import envi

Daniele Faraglia 2.7k Jan 7, 2023
Generate generic activity streams from the actions on your site. Users can follow any actors' activities for personalized streams.

Django Activity Stream What is Django Activity Stream? Django Activity Stream is a way of creating activities generated by the actions on your site. I

Justin Quick 2.1k Dec 29, 2022
Easily share data across your company via SQL queries. From Grove Collab.

SQL Explorer SQL Explorer aims to make the flow of data between people fast, simple, and confusion-free. It is a Django-based application that you can

Grove Collaborative 2.1k Dec 30, 2022
Rosetta is a Django application that eases the translation process of your Django projects

Rosetta Rosetta is a Django application that facilitates the translation process of your Django projects. Because it doesn't export any models, Rosett

Marco Bonetti 909 Dec 26, 2022
Simple yet powerful and really extendable application for managing a blog within your Django Web site.

Django Blog Zinnia Simple yet powerful and really extendable application for managing a blog within your Django Web site. Zinnia has been made for pub

Julien Fache 2.1k Dec 24, 2022
Management commands to help backup and restore your project database and media files

Django Database Backup This Django application provides management commands to help backup and restore your project database and media files with vari

null 687 Jan 4, 2023
Use Database URLs in your Django Application.

DJ-Database-URL This simple Django utility allows you to utilize the 12factor inspired DATABASE_URL environment variable to configure your Django appl

Jacob Kaplan-Moss 1.3k Dec 30, 2022
Use heroicons in your Django and Jinja templates.

heroicons Use heroicons in your Django and Jinja templates. Requirements Python 3.6 to 3.9 supported. Django 2.2 to 3.2 supported. Are your tests slow

Adam Johnson 52 Dec 14, 2022
Add Chart.js visualizations to your Django admin using a mixin class

django-admincharts Add Chart.js visualizations to your Django admin using a mixin class. Example from django.contrib import admin from .models import

Dropseed 22 Nov 22, 2022