Skip to content

Take a break from javascript. Write server-rendered reactive HTML liveviews for Django in pure python πŸ’«

License

Notifications You must be signed in to change notification settings

runekaagaard/django-hypergen

Repository files navigation

Welcome to Django Hypergen

Take a break from javascript

Write server-rendered reactive HTML liveviews for Django in pure python πŸ’«

Homepage Β Β β€’Β Β  Documentation Β Β β€’Β Β  Support

Hypergen: A Hypertext Generator: Craft templates using pure Python. Instead of declaring <p>hi</p> in an HTML file, simply invoke p("hi") within your view. Composing Python functions keeps templates DRY and streamlined. If you've ever written JSX, Hypergen's syntax will feel familiar.

Reactive Liveviews: Effortlessly bridge frontend and backend. Connect browser events like onclick straight to backend actions. With these actions, Django views can instantly refresh the frontend with new HTML, send notifications, and more, all while natively working with Python data types.

Websockets: Hypergen brings realtime to the forefront with Django Channels. Set up is a breeze - quickly establish consumers and instantly react to live events. It's realtime made simple and friendly, just the way we like it.

Production Ready: We've deployed Hypergen in projects spanning tens of thousands of lines, serving over 100,000 unique users more than 10 million requests.

Quickstart: Kickstart your Hypergen journey in minutes. Execute pip install django-hypergen, append 'hypergen' to INSTALLED_APPS, include 'hypergen.context.context_middleware' in MIDDLEWARE, and you're all set to dive in.

How does it look?

Using Hypergens most high-level constructs, a simple counter looks like this:

@liveview(perm=NO_PERM_REQUIRED)
def counter(request):
    with html(), body(), div(id="content"):
        template(0)

@action(perm=NO_PERM_REQUIRED, target_id="content")
def increment(request, n):
    template(n + 1)

def template(n):
    label("Current value: ")
    input_el = input_(id="n", type_="number", value=n)
    button("Increment", id="increment", onclick=callback(increment, input_el))

You can see it in action.

The callback(func, arg1, arg2, ..., **settings) function connects the onclick event to the increment(request, n) action. The n argument is the value of the input field.

DOM elements are nested with the with statement.

It's python all the way down. πŸ”₯πŸ”₯πŸ”₯

Features

  • 🧩 Composable - structure your app with ... TADAAA ... python functions
  • 🌐 Less infrastructure - take a break from npm, npx, yarn, webpack, parcel, react, redux, gulp, angular, vue and friends
  • πŸš€ Build truly singlepage apps - avoid abstraction gaps to a template language and javascript
  • ⏳ Async not needed - uses the vanilla Django Request-Response cycle by default
  • πŸ”€ Automatic (de)serialization - use python builtin types and move on
  • 🎯 No magic strings - reactivity is defined by referencing python functions
  • πŸ“¦ Free partial loading - no special setup required, includes back/forward history support
  • πŸ”’ Control over client side events - inbuilt confirmation dialogs, blocking and debouncing
  • πŸ“€ Easy uploading of files - with progress bar
  • πŸ’› Still loves javascript - trivially call client functions from the server
  • ⚑ Realtime - Create websocket consumers trivially
  • πŸ“œ History buff? - don't worry, Hypergen supports from Django 1.11, Python 3.6 and up to as of this writing Django 4.2.6 and python 3.12.
  • πŸ› οΈ Hyperfy - the command line app that converts html to hypergen python code

Running the examples

git clone git@github.com:runekaagaard/django-hypergen.git
cd django-hypergen/
virtualenv -p python3.9 venv
source venv/bin/activate
pip install -r requirements-dev.txt
cd examples
python manage.py runserver

Then browse to http://127.0.0.1:8000.

Contributing

Bug reports and feature requests are very welcome. So are pull requests or diffs.

Authors

Hypergen is written by Jeppe Tuxen and Rune Kaagaard, both located around Copenhagen, Denmark.

We are using Hypergen extensively at work so it's a big focus of ours.

Why not Hypergen?

  • Every frontend event calls the server. Not good for e.g. games.
  • Python templating might not be for everyone. We found it works great in practice.

Developing

Backend

Hypergen is located in src/hypergen. Format all python code with yapf, a .yapf config file is present in the repository.

Frontend

Compile the javascript files:

cd hypergen/static/hypergen
npm install # use node 18 lts
# watch hypergen.js to dist/hypergen.js
npm start
# build hypergen.js to dist/hypergen.js
npm run build

Profiling

How fast are we?:

rm -f /tmp/hypergen.profile && python -m cProfile -o /tmp/hypergen.profile manage.py runserver 127.0.0.1:8002
echo -e 'sort tottime\nstats' | python3 -m pstats /tmp/hypergen.profile | less

# or
pyprof2calltree -i /tmp/hypergen.profile -k

# or
rm -f /tmp/hypergen.profile && python -m cProfile -o /tmp/hypergen.profile manage.py inputs_profile && \
    echo -e 'sort tottime\nstats' | python3 -m pstats /tmp/hypergen.profile | less

Testing

We have a Github Action that automatically tests a matrix of Django and Python versions. You can run the pytest tests locally like so:

pip install -r requirements-dev.txt
make pytest-run

And the testcafe end-to-end_ tests:

npm i -g testcafe
make testcafe-run
# or
make testcafe-run-headless

Requires that the examples are running on 127.0.0.1:8002.

Thanks

  • Django - for making work fun
  • Morphdom - for fast updating of the DOM tree
  • Pyrsistent - for providing an immutable dict
  • sockette - The cutest little WebSocket wrapper! 🧦
  • Simple.css - for the no-class styling on the homepage
  • DALL-E mini - for the logo generated with the query "a vibrant logo of the letter H"

About

Take a break from javascript. Write server-rendered reactive HTML liveviews for Django in pure python πŸ’«

Topics

Resources

License

Stars

Watchers

Forks