django
django copied to clipboard
Django Logux integration engine https://logux.io/
Logux Django
Django Logux integration engine.
- Guide, recipes, and API
- Issues and roadmap
- Projects inside Logux ecosystem
Installation
Install from PyPI
pip install logux-django
Install dev version from current master.
pip install -e git://github.com/logux/django.git#egg=logux_django
Add path(r'logux/', include('logux.urls')), into your urls.py
Sets Logux settings in your settings.py:
# Logux settings: https://logux.org/guide/starting/proxy-server/
LOGUX_CONFIG = {
'URL': 'http://localhost:31337/',
'CONTROL_SECRET': 'parole',
'AUTH_FUNC': auth_func, # auth_func(user_id: str, token: str, cookie: dict, headers: dict) -> bool
'SUBPROTOCOL': '1.0.0',
'SUPPORTS': '^1.0.0'
}
Storing passwords or secrets in settings.py is bad practice. Use ENV.
For urls and settings examples, please checkout test_app
settings
Keep in mind: the path in your urls.py (logux/) and the LOGUX_CONTROL_SECRET from the settings should be passed
into Logux Server by ENV as
LOGUX_BACKEND and LOGUX_CONTROL_SECRET respectively.
For example:
LOGUX_BACKEND=http://localhost:8000/logux/
LOGUX_CONTROL_SECRET=secret
Usage
Actions
For action handling add logux_actions.py file in your app, add ActionCommand inheritors and implement all his
abstract methods.
Actions classes requirements:
- Set
action_type: str - Implement all
ActionCommandabstracts methods - Implement
resendandprocessmethods if you need (optional) - import
loguxdispatcher:from logux.dispatchers import logux - Register all your action handlers:
logux.actions.register(YourAction)
For example – User rename action handler:
import json
from typing import Optional, List
from logux.core import ActionCommand, Meta, Action
from logux.dispatchers import logux
from logux.exceptions import LoguxProxyException
from tests.test_app.models import User
class RenameUserAction(ActionCommand):
""" During the subscription to users/USER_ID channel sends { type: "users/name", payload: { userId, name } }
action with the latest user’s name. """
action_type = 'users/name'
def resend(self, action: Action, meta: Optional[Meta]) -> List[str]:
return [f"users/{action['payload']['userId']}"]
def access(self, action: Action, meta: Meta) -> bool:
if 'error' in self.headers:
raise LoguxProxyException(self.headers['error'])
return action['payload']['userId'] == meta.user_id
def process(self, action: Action, meta: Meta) -> None:
user = User.objects.get(pk=action['payload']['userId'])
first_name_meta = json.loads(user.first_name_meta)
if not first_name_meta or Meta(first_name_meta).is_older(meta):
user.first_name = action['payload']['name']
user.first_name_meta = meta.get_json()
user.save()
logux.actions.register(RenameUserAction)
Channels (Subscription)
For subsription handling add logux_subsriptions.py file in your app, and ChannelCommand inheritors
and implement all his abstract methods.
Subscription classes requirements:
- Set
channel_pattern: str– this is a regexp like Django's url's patters inurls.py - Implement all
ChannelCommandabstracts methods - import
loguxdispatcher:from logux.dispatchers import logux - Register all your subscription handlers:
logux.channels.register(YourChannelCommand)
For example:
from typing import Optional
from logux.core import ChannelCommand, Action, Meta
from logux.dispatchers import logux
from logux.exceptions import LoguxProxyException
from tests.test_app.models import User
class UserChannel(ChannelCommand):
channel_pattern = r'^users/(?P<user_id>\w+)$'
def access(self, action: Action, meta: Meta) -> bool:
return self.params['user_id'] == meta.user_id
def load(self, action: Action, meta: Meta) -> Action:
if 'error' in self.headers:
raise LoguxProxyException(self.headers['error'])
user, created = User.objects.get_or_create(id=self.params['user_id'])
if created:
user.first_name = 'Name'
return {
'type': 'users/name',
'payload': {'userId': str(user.id), 'name': user.first_name}
}
logux.channels.register(UserChannel)
For more examples, please checkout test app (tests/test_app)
Utils
logux.core.logux_add
logux_add(action: Action, raw_meta: Optional[Dict] = None) -> None is low level API function to send any actions and meta into Logux server.
If raw_meta is None just empty Dict will be passed to Logux server.
Keep in mind, in the current version logux_add is sync.
For more information: https://logux.org/node-api/#log-add
Development
We use Poetry and dephell for dealing with deps.
Create dev environment, setup logux in develop mode, run local test server
make deps
make install
make run
Type checking and linting:
make lint
Test:
make test
Integration tests (up server and run backend-test).
Install backend-test deps:
make lbt_deps
Run integration tests
make integration_test
License
The package is available as open source under the terms of the MIT License.