Coder Social home page Coder Social logo

adamghill / django-unicorn Goto Github PK

View Code? Open in Web Editor NEW
2.3K 24.0 118.0 4.84 MB

The magical reactive component framework for Django ✨

Home Page: https://www.django-unicorn.com

License: MIT License

Python 67.41% JavaScript 26.85% HTML 5.73% CSS 0.01%
django python javascript fullstack frontend-framework

django-unicorn's Introduction

django-unicorn logo

Unicorn

The magical reactive component framework for Django ✨

PyPI PyPI - Downloads coverage GitHub Sponsors All Contributors

Unicorn adds modern reactive component functionality to your Django templates without having to learn a new templating language or fight with complicated JavaScript frameworks. It seamlessly extends Django past its server-side framework roots without giving up all of its niceties or forcing you to rebuild your application. With Django Unicorn, you can quickly and easily add rich front-end interactions to your templates, all while using the power of Django.

https://www.django-unicorn.com has extensive documentation, code examples, and more!

⚡ Getting started

pip install django-unicorn OR poetry add django-unicorn

2. Add django_unicorn to INSTALLED_APPS

# settings.py
INSTALLED_APPS = (
    # other apps
    "django_unicorn",
)

3. Update urls.py

# urls.py
import django_unicorn

urlpatterns = (
    # other urls
    path("unicorn/", include("django_unicorn.urls")),
)

4. Add Unicorn to the HTML template

<!-- template.html -->
{% load unicorn %}

<html>
  <head>
    {% unicorn_scripts %}
  </head>
  <body>
    {% csrf_token %}
  </body>
</html>

python manage.py startunicorn myapp COMPONENT_NAME

Unicorn uses the term "component" to refer to a set of interactive functionality that can be put into templates. A component consists of a Django HTML template and a Python view class which contains the backend code. After running the management command, two new files will be created:

  • myapp/templates/unicorn/COMPONENT_NAME.html (component template)
  • myapp/components/COMPONENT_NAME.py (component view)

6. Add the component to your template

<!-- template.html -->
{% load unicorn %}

<html>
  <head>
    {% unicorn_scripts %}
  </head>
  <body>
    {% csrf_token %}

    {% unicorn 'COMPONENT_NAME' %}
  </body>
</html>

The unicorn: attributes bind the element to data and can also trigger methods by listening for events, e.g. click, input, keydown, etc.

<!-- todo.html -->

<div>
  <form unicorn:submit.prevent="add">
    <input type="text"
      unicorn:model.defer="task"
      unicorn:keyup.escape="task=''"
      placeholder="New task" id="task"></input>
  </form>
  <button unicorn:click="add">Add</button>
  <button unicorn:click="$reset">Clear all tasks</button>

  <p>
    {% if tasks %}
      <ul>
        {% for task in tasks %}
          <li>{{ task }}</li>
        {% endfor %}
      </ul>
    {% else %}
      No tasks 🎉
    {% endif %}
  </p>
</div>
# todo.py

from django_unicorn.components import UnicornView
from django import forms

class TodoForm(forms.Form):
    task = forms.CharField(min_length=2, max_length=20, required=True)

class TodoView(UnicornView):
    task = ""
    tasks = []

    def add(self):
        if self.is_valid():
            self.tasks.append(self.task)
            self.task = ""

✨ Wait, is this magic?

Sort of! At least it might feel like it. 🤩

  1. Unicorn progressively enhances a normal Django view, so the initial render is fast and great for SEO.
  2. Unicorn binds to the elements you specify and automatically makes AJAX calls when needed.
  3. Unicorn seamlessly updates the DOM when the HTML changes.

Focus on building regular Django templates and Python classes without needing to switch to another language or use unnecessary infrastructure.

🤯 But wait, there's more!

As if that wasn't enough, other features include:

📖 Dig In

❤️ Support

This project is supported by GitHub Sponsors and Digital Ocean.

🔧 Contributors

Check out this guide for more details on how to contribute.

Thanks to the following wonderful people (emoji key) who have helped build Unicorn.

Adam Hill
Adam Hill

💻 ⚠️
Andres Vargas
Andres Vargas

💻
Eddy Ernesto del Valle Pino
Eddy Ernesto del Valle Pino

💻
Yaser Al-Najjar
Yaser Al-Najjar

💻
Stephan Traub
Stephan Traub

⚠️
Fredrik Borg
Fredrik Borg

💻 ⚠️
mbacicc
mbacicc

💻
Ron
Ron

📖
Franziskhan
Franziskhan

💻
Josh Higgins
Josh Higgins

⚠️ 💻
Amayas Messara
Amayas Messara

💻
Apoorva Pandey
Apoorva Pandey

⚠️ 💻
Christian González
Christian González

💻 📖
robwa
robwa

💻 ⚠️
Preston Badeer
Preston Badeer

📖
Sergei
Sergei

📖 💻 ⚠️
bazubii
bazubii

💻 ⚠️
Dan Caron
Dan Caron

📖
Shantanu
Shantanu

💻
regoawt
regoawt

💻 ⚠️
Lasse H. Bomholt
Lasse H. Bomholt

💻
Martey Dodoo
Martey Dodoo

📖
Pierre
Pierre

💻
Roman Imankulov
Roman Imankulov

⚠️ 💻
Lemi Boyce
Lemi Boyce

💻
Jack Sundberg
Jack Sundberg

💻
siliconcow
siliconcow

💻 ⚠️
Akintola Rahmat
Akintola Rahmat

💻
Mario Munoz
Mario Munoz

📖
Emily Wood
Emily Wood

💻
Jeremy Wright
Jeremy Wright

💻

This project follows the all-contributors specification. Contributions of any kind welcome!

django-unicorn's People

Contributors

adamghill avatar allcontributors[bot] avatar apoorvaeternity avatar bazubii avatar bloodywing avatar clangley avatar dancaron avatar edelvalle avatar epw1624 avatar felipmartins avatar franziskhan avatar frnidito avatar github-actions[bot] avatar hauntsaninja avatar hendi avatar imankulov avatar jacksund avatar jeremylwright avatar joshiggins avatar lassebomh avatar martey avatar mihrab34 avatar nerdoc avatar pbadeer avatar regoawt avatar rhymiz avatar robwa avatar s1liconcow avatar stat1c-void avatar zodman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-unicorn's Issues

Handle `lazy` modifier

Add support for unicorn:model.lazy to change the event listener to be blur instead of input.

loading delay modifier

To prevent flicker only show/remove unicorn:loading when the action takes longer than 200ms.

Model bind to a nested property

Either a property array, dictionary or object. Probably should use dot notation to access.

e.g. <input type="text" unicorn:model="blog.author.name">

Possible directory error in default examples

Hi. I've created an empty django project to test unicorn. But somehow the default instructions don't seem to work and cause a template not found error. Here's what I've done:

  1. Created a new django project in pycharm
  2. pip install django-unicorn
  3. Added "django_unicorn", to the INSTALLED_APPS
  4. Created an empty base.html file and made it viewable in the browser
  5. Added path("unicorn/", include("django_unicorn.urls"))
  6. Added {% load unicorn %} to the top of base.html
  7. Added {% unicorn_scripts %} right underneath in base.html
  8. Ran python manage.py startunicorn hello-world
  9. Added {% unicorn 'hello-world' %} at the bottom of base.html

After this last step 9 it starts to break and throws a TemplateDoesNotExist error:
django.template.loaders.filesystem.Loader: /home/user/uniplayground/templates/unicorn/hello-world.html (Source does not exist)

In my project folder the hello-world.html file generated by step 8 is located under:
/home/user/uniplayground/unicorn/templates/unicorn/hello-world.html

Am I doing something wrong or does the startunicorn command not generate the files into the right structure?

Edit: Moving the HTML file to the template folder that django is looking in seems to work. While leaving the python file in the generated folder structure.

$model special action variable

It would be useful to handle the special action argument $model being passed into an action. Probably only useful for db models since normal models can just do self.whatever in the component view code.

<div>
  {% for book in books %}
  <div u:db="book" u:pk="{{ book.id }}">
    <button u:click="delete($model)`>
    <!-- <button u:click="delete({{ book.id }})`> -->
  </div>
  {% endfor %}
</div>
from django_unicorn.components import UnicornView
from books.models import Book

class DbModelView(UnicornView):
    # magically instantiate the appropriate book instance object here based on model class and pk
    def delete(book):
         book.delete()

    # normal way call action with a model requires passing around an id/pk/slug and looking it up
    # def delete(book_id):
    #    book = Book.objects.get(id=book_id)
    #    book.delete()

    class Meta:
        db_models = [DbModel("book", Book)]

Django model on property doesn't reset as expected

When using a Django model as a property, if a field is updated as part of unicorn:model, the model will not get reset as expected.

class HelloWorldView(UnicornView):
    book = Book(title="The Sandman")
<input unicorn:model="book.title" type="text" id="bookId">

When a model and action fire at the same time, the sync input can be lost

I was not seeing this on local dev with 0.6.0, but it happens when deployed. I am now able to replicate it on local by throttling network responses.

I think I need to merge the syncInput and callMethod actions that fire "at the same time" into the payload array so that the syncInput doesn't get lost.

Looks promising

How can I help? I’m a web designer/developer (HTML + CSS) and haven’t taken the leap into the front-end frameworks.

I like the idea of components but all of the overhead in the front-end frameworks is overwhelmingly complex and changes far too often to keep up with a small team.

We have a couple of projects which use Django with templates.

This project looks like something we would be interested in.

How can we help?

Set property shortcut

Instead of having to create set_name() methods, support something like name='World'.

Interaction glitch w/ BitWarden

hello Adam, long time no talk!

I was trying out the demo on the website and something BitWarden is doing to the input box, I think added it's own attribute to the html, causes the input to be redrawn empty but if you click the button add it will still load something but not everything.

Video:
django-unicorn-glitch.mov.zip

If I disable BitWarden and reload the page, the interaction works fine.

Updating class variables from outside

HI Adam!

It would be useful to be able to update the unicorn component class variables from another Django app.
You mentioned an API call or database hookup on the page refresh.
How would this be done?

Would this also be possible via AJAX or a Javascript hook?

Thanks!

Ashirvad

Cast to a particular property type

Strings and booleans get cast as expected, but it'd be nice to have a mechanism to cast to a particular type inside the component. The canonical example would be a datetime coming from a HTML input and getting parsed to be a datetime` object inside the component.

Reduce lag with keeping text input up to date

Example: django-unicorn-lag

Not sure if this is related to morphdom updating the DOM in a way not expected. Maybe need to prevent the current model name from being updated by morphdom? Or maybe just reduce the debounce timeout might make it work a little better?

Passing arguments to the unicorn view

Being able to send arguments from the parent django template to the unicorn view.

To be able to do something like :

class TestView(UnicornView):
    name = "hello-world"
    def __init__(self, var):
         self.var = var
    def set_var(self, var):
         self.var = var
{% unicorn 'hello-world' with var=var %}      (django {% include %} like )

Or to be able to send arguments to Unicorn.call :

{% unicorn 'hello-world' %}

<button onclick="Unicorn.call('hello-world', 'set_var', 'var_value');">Set the name from outside the component</button>

Even if it's just sending a one-shot primitives it will be very helpful to give some context to the unicorn view.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.