All Projects → ApplauseOSS → Djangoevents

ApplauseOSS / Djangoevents

Licence: mit

Programming Languages

python
139335 projects - #7 most used programming language

Projects that are alternatives of or similar to Djangoevents

Eventsourcing
A library for event sourcing in Python.
Stars: ✭ 760 (+1051.52%)
Mutual labels:  event-sourcing, django
Thinkdiff
My open source project links, programming and software development related code and tutorials are in this repo. Content types: Python, JavaScript, Dart | Django, React, Flutter, React-Native etc.
Stars: ✭ 65 (-1.52%)
Mutual labels:  django
Django Anymail
Django email backends and webhooks for Amazon SES, Mailgun, Mailjet, Postmark, SendGrid, Sendinblue, SparkPost and more
Stars: ✭ 1,109 (+1580.3%)
Mutual labels:  django
Webterminal
ssh rdp vnc telnet sftp bastion/jump web putty xshell terminal jumpserver audit realtime monitor rz/sz 堡垒机 云桌面 linux devops sftp websocket file management rz/sz otp 自动化运维 审计 录像 文件管理 sftp上传 实时监控 录像回放 网页版rz/sz上传下载/动态口令 django
Stars: ✭ 1,124 (+1603.03%)
Mutual labels:  django
Djaoapp
User login, billing, access control as part of a session proxy
Stars: ✭ 61 (-7.58%)
Mutual labels:  django
Taggit Selectize
Auto-complete/auto-suggestion for django-taggit (django-taggit + selectize.js)
Stars: ✭ 63 (-4.55%)
Mutual labels:  django
Akka Tools
Open source tools to simplify Akka event sourcing, journaling/persistence, serialization, clustering and sharding.
Stars: ✭ 60 (-9.09%)
Mutual labels:  event-sourcing
Wemake Django Template
Bleeding edge django template focused on code quality and security.
Stars: ✭ 1,141 (+1628.79%)
Mutual labels:  django
Django Statsy
Statistics for your Django project
Stars: ✭ 64 (-3.03%)
Mutual labels:  django
Best Of Web Python
🏆 A ranked list of awesome python libraries for web development. Updated weekly.
Stars: ✭ 1,118 (+1593.94%)
Mutual labels:  django
Django Crm
A Simple Django CRM (Customer Relationship Management) RESTful API Project
Stars: ✭ 63 (-4.55%)
Mutual labels:  django
Django Taggit Labels
Clickable label widget for django-taggit
Stars: ✭ 62 (-6.06%)
Mutual labels:  django
Mrdoc
online document system developed based on python. It is suitable for individuals and small teams to manage documents, wiki, knowledge and notes. like gitbook.
Stars: ✭ 1,129 (+1610.61%)
Mutual labels:  django
Django Chinese Docs 18
📖 [译] django 中文文档协作翻译计划
Stars: ✭ 61 (-7.58%)
Mutual labels:  django
Osis
Open Student Information System Backoffice
Stars: ✭ 65 (-1.52%)
Mutual labels:  django
Cookiecutter Django Rest
Build best practiced apis fast with Python3
Stars: ✭ 1,108 (+1578.79%)
Mutual labels:  django
Django React
This a simple Django and React demo application
Stars: ✭ 63 (-4.55%)
Mutual labels:  django
Sapl
Sistema de Apoio ao Processo Legislativo
Stars: ✭ 63 (-4.55%)
Mutual labels:  django
Facial Recognition Python Django
Face detection and facial recognition along with recognized persons information fetched from database.
Stars: ✭ 66 (+0%)
Mutual labels:  django
Django Polymorphic
Improved Django model inheritance with automatic downcasting
Stars: ✭ 1,135 (+1619.7%)
Mutual labels:  django

Welcome to djangoevents' documentation!

djangoevents offers building blocks for building Event Sourcing Django applications.

Build Status Build Status

Setup

Install with pip:

pip install djangoevents

Include in settings.py:

INSTALLED_APPS = [
    ...
    'djangoevents',
    ...
]

Event Sourcing Components

djangoevents takes advantage of eventsourcing library for handling event sourcing and replaces its storage backend with Django Model for seamless integration with Django.

BaseAggregate

It is required to place all aggregate definitions in aggregates.py module of a Django application.

BaseEntity is a wrapper over EventSourcedEntity from eventsourcing's EventSourcedEntity. It is used to define Aggregates, its domain events and how domain events apply changes to Aggregates in one place.

from djangoevents import BaseAggregate

class Todo(BaseAggregate):

    class Created(BaseAggregate.Created):
        def mutate_event(self, event, cls):
            return cls(
                entity_id=event.entity_id,
                entity_version=event.entity_version,
                domain_event_id=event.domain_event_id,
                label=event.label,
                done=False,
            )

    class ChangedLabel(BaseAggregate.AttributeChanged):
        def mutate_event(self, event, instance):
            instance.label = event.label
            return instance

EventSourcingWithDjango

For seamless integration with Django, we created an implementation of eventsourcing's eventStore using Django ORM and built EventSourcingWithDjango on top of it. By using EventSourcingWithDjango, the Django ORM will be used to store events. Here is a short example of how to create and save an event:

from djangoevents import EventSourcingWithDjango
from djangoevents import store_event

class Todo(EventSourcedEntity):
    ...

class TodoRepository(EventSourcedRepository):
    domain_class = Todo

es_app = EventSourcingWithDjango()
repo = es_app.get_repo_for_entity(Todo)

# publish event (saves in the database)
todo_created_event = Todo.Created(
    entity_id='6deaca4c-d866-4b28-9878-8814a55a4688',
    label='my next thing to do',
    metadata={'command_id': '...'}
)
store_event(todo_created_event)

# get todo aggregate from repo by aggregate id
my_todo = repo['6deaca4c-d866-4b28-9878-8814a55a4688']

Event handlers

If extra event handling on event publish other than saving it to event journal is a requirement, add handlers.py file in your app and use subscribe_to decorator with the DomainEvent class you intent to listen on. Example:

from djangoevents import subscribe_to
from myapp.entities import Miracle

@subscribe_to(Miracle.Happened)
def miracle_handler(event):
    print(" => miracle happened! update your projections here!")

Note: name of that file is important. There is auto-import mechanism that would import handlers.py file for all apps mentioned in INSTALLED_APPS. You can put handler functions anywhere you like but you'd need to make sure it's imported somehow.

Import shortcuts

We have ported commonly used functionality from eventsourcing to the top level of this library. Please import from djangoevents because we might have extended functionality of some classes and functions.

from djangoevents import DomainEvent                    # from eventsourcing.domain.model.entity import DomainEvent
from djangoevents import EventSourcedEntity             # from eventsourcing.domain.model.entity import EventSourcedEntity
from djangoevents import entity_mutator                 # from eventsourcing.domain.model.entity import entity_mutator
from djangoevents import singledispatch                 # from eventsourcing.domain.model.entity import singledispatch

from djangoevents import store_event                    # from eventsourcing.domain.model.events import publish
from djangoevents import subscribe                      # from eventsourcing.domain.model.events import subscribe
from djangoevents import unsubscribe                    # from eventsourcing.domain.model.events import unsubscribe

from djangoevents import subscribe_to                   # from eventsourcing.domain.model.decorators import subscribe_to

from djangoevents import EventSourcedRepository         # from eventsourcing.infrastructure.event_sourced_repo import EventSourcedRepository

Documenting event schema

Event schema validation is disabled by default. To enable it for the whole project please add DJANGOEVENTS_CONFIG to project's settings.py:

DJANGOEVENTS_CONFIG = {
    ...
    'EVENT_SCHEMA_VALIDATION': {
        'ENABLED': True,
        'SCHEMA_DIR': 'avro',
    },
    ...
}

Once this is enabled avro schema definition will be required for all events in the system. The only exception to this rule are events of abstract aggregates:

from djangoevents import BaseAggregate, abstract

@abstract
class Animal(BaseAggregate):
    class Created(BaseAggregate.Created):
        def mutate_event(self, event, cls):
            return cls(
                entity_id=event.entity_id,
                entity_version=event.entity_version,
                domain_event_id=event.domain_event_id,
                label=event.label,
                done=False,
            )

class Dog(Animal):
    pass

In the example above Animal was defined as an abstract aggregate. Its goal is to keep all common implementation in a single place for child classes. No event specification is required for Animal.Created abstract aggregates. It needs to be present for Dog.Created though.

It is expected that each service will fully document all events emitted through avro schema definitions. Read more about avro format specification.

By default djangoevents assumes event schemas will be placed in avro folder located at project's root directory as specifed below:

$ tree project
|- src
|--- manage.py
|--- ..
|-avro
|--- aggragate_name/
|----- v1_aggregate_name_test_event1.json
|----- v1_aggregate_name_test_event2.json
...
$ cat avro/aggragate_name/v1_aggregate_name_test_event1.json

{
  "name": "aggregate_name_test_event1",
  "type": "record",
  "doc": "Sample Event",
  "fields": [
    {
      "name": "entity_id",
      "type": "string",
      "doc": "ID of a the asset."
    },
    {
      "name": "entity_version",
      "type": "long",
      "doc": "Aggregate revision"
    },
    {
      "name": "domain_event_id",
      "type": "string",
      "doc": "ID of the last modifying event"
    },
  ]
}

Once event schema validation is enabled for your services, following changes will apply:

  • At startup (djangoevents.AppConfig.ready()) schemas of events of all non-abstract aggregates will be loaded, validated & cached. If any error occurs warning message will be printed in the console.
  • store_event() will validate your event before storing it to the event journal.

In cases where enabling validation for the whole project is not possible you can enforce schema validation on-demand by adding force_valdate=True parameter to store_event() call.

Event version

djangoevents detects the latest version of your event based on Avro schema files it finds. Version is stored as the .version property of an event class, e.g. SomeEvent.version. Version is added to stored event envelope under the event_version key.

For compatibility with some systems, we provide an option to add event version to event data as well (essentially stored_event.event_data['schema_version'] = stored_event.event_version). This functionality is disabled by default, but you can enable it in your project's settings:

DJANGOEVENTS_CONFIG = {
    ...
    'ADDS_SCHEMA_VERSION_TO_EVENT_DATA': True,
    ...
}

Development

Build

$ make install

Run tests

$ source venv/bin/activate
$ pytest
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].