Phoenix LiveView but for Django
Breaking changes in how to test components, for better
Using async with reactor() as comm
, you get an object that you can use to register components, send commands... doc
is a PyQuery object containing the HTML rendering of the object, so you can perform checkings of the rendering of the object.
from pytest import mark
from channels.db import database_sync_to_async as db
from reactor.tests import reactor
@mark.django_db(transaction=True)
async def test_live_components():
x_list = comm.add_component(
'x-todo-list',
{'id': 'someid', 'showing': 'all'}
)
x_todo_counter = comm.add_component(
'x-todo-counter',
{'id': 'someid-counter'}
)
doc = await comm.send_join(x_list)
todo_list = doc('#someid')
assert json.loads(todo_list.attr['state']) == comm[x_list].state
# Add new item
doc = await comm.send(x_list, 'add', new_item='First task')
# There was an item crated and rendered
assert await db(Item.objects.count)() == 1
assert len(doc('x-todo-item')) == 1
todo_item_id = doc('x-todo-item')[0].get('id')
todo_item_label = doc('x-todo-item label')[0]
assert todo_item_label.text == 'First task'
Added:
Component.send_redirect
has a new parameter push_state=True
, when set it will do a push state in the front-end.push_state(url)
to trigger this in the front-end.reactor.component.send_to_group
to reactor.broadcast
REACTOR_AUTO_BROADCAST = True
will trigger broadcast updates when models instances are manipulated.AuthComponent
and StaffComponent
debounce
function to send events to the backend.reactor-once
when an element is market with it, it will not be updated.ReactorChannel.reconnect
, closes the connection and reopens it.public
parameter to class inheritance, so you can decide if the element is exposed or not.atomic
transactions. You will have to put @atomic
when you want something to be atomic. The reason for this is that some events don't have to deal at all with the database because they just change the local state of the component.reactor.broadcast(*names)
: this broadcasts the messages that you can subscribe to using Component.subscribe()
.Component.send_redirect(url)
: now you can send a URL redirect to the front-end, when the component is being rendered for first time the redirect is rendered as a <meta http-equiv="refresh" content="0; url={{ url }}">
, if the component is alive then the front-end controller executes the redirect.AuthComponent
, this component has a user
attributed taken from the Component._context
and on mount
if the user is authenticated returns the True, if the user is not returns None
and sends a redirect to settings.LOGIN_URL
. <input name="query" value="q">
<input name="persons[].name" value="a">
<input name="persons[].name" value="b">
This will be serialized as: {query: "q", persons: [{name: "a"}, {name: "b"}]}
send_redirect(url)
. Example:def receive_save(self, name, **kwargs):
self.instance.name = name
self.instance.save()
self.send_redirect(self.instance.get_absolute_url())
div
and this can be redefined by the user overwriting the extends
attribute. Example:class MySpecialInput(Component):
extends = 'input'