Quickstart

Installation

$ pip install django-siteajax

Configuration

In your project configuration file (usually settings.py):

  1. Add siteajax to INSTALLED_APPS.

  2. Add siteajax.middleware.ajax_handler to MIDDLEWARE.

Note

The middleware is required if either your site is ajax-heavy (the majority of requests are ajax) or you do not use @ajax_dispatch decorator (it initializes request.ajax property just as middleware does) described below.

Basic Usage

Somewhere in your views.py:

from django.shortcuts import redirect, render
from siteajax.toolbox import Ajax, AjaxResponse


def index_page(request):
    """Suppose this view is served at /"""

    ajax: Ajax = request.ajax

    if ajax:

        news = ...  # Here we fetch some news from DB.

        response = render(request, 'mytemplates/sub_news.html', {'news': news})

        # Now we can already return the response as usual.
        # But let's instruct the client side
        # to do some tricks. For that we use AjaxResponse wrapper:
        response = AjaxResponse(response)
        # Let's trigger `newsReady` event defined on client side
        # and pass some params into it:
        response.trigger_event(name='newsReady', kwargs={'count': len(news)})

        return response

    return render(request, 'mytemplates/index.html')

Now to your mytemplates/index.html:

<!DOCTYPE html>
<html>
<head>
    <!-- Get client library js from CDN. -->
    {% include "siteajax/cdn.html" %}
</head>
<body>
    <div id="news-list" hx-get hx-trigger="load"></div>
    <!-- The contents of the above div will be replaced
        with news from server automatically fetched on page load. -->

    <!-- Initialize CSRF token for Django (if you ever want to use POST/PUT etc.) -->
    <script>{% include "siteajax/init_csrf.js" %}</script>

    <script>
        document.body.addEventListener('newsReady', function(event){
           alert('News loaded: ' + event.detail.count);
        })
    </script>

</body>
</html>

At last mytemplates/sub_news.html (nothing special):

{% for item in news %}<div>{{ item.title }}</div>{% endfor %}

Note

See https://htmx.org/docs/ for more examples of client side

Dispatch

In cases when various ajax calls have a single entry point view it’s useful to apply siteajax.toolbox.Ajax.ajax_dispatch decorator to decouple logic.

It allows ajax request dispatch based on source html element identifiers. So the above mentioned index_page entry point view can be defined as follows

from django.shortcuts import redirect, render
from siteajax.toolbox import AjaxResponse, ajax_dispatch


def get_news(request):
    news = ...  # Here we fetch some news from DB.
    response = AjaxResponse(render(request, 'mytemplates/sub_news.html', {'news': news}))
    response.trigger_event(name='newsReady', kwargs={'count': len(news)})
    return response

@ajax_dispatch({
    'news-list': get_news,  # Map element id to a handler
})
def index_page(request):
    """Suppose this view is served at /"""
    return render(request, 'mytemplates/index.html')

For cases when you want to route multiple autogenerated page elements with IDs having a common prefix (e.g.: in myel-1, myel-44, myel-something common prefix is myel-) to a single handler use star (*):

@ajax_dispatch({
    'myel-*': common_handler,
})
def my_iew(request):
    ...