Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: read the docs added #16

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,9 @@
"source.organizeImports": true
}
},
"isort.args": ["--profile", "black"]
"isort.args": [
"--profile",
"black"
],
"esbonio.sphinx.confDir": ""
}
20 changes: 20 additions & 0 deletions docs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
27 changes: 27 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

project = 'drf-webhooks'
copyright = '2023, demux'
author = 'demux'
release = '22.01.23'

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

extensions = ['myst_parser']

templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']


# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

html_theme = 'alabaster'
html_static_path = ['_static']
125 changes: 125 additions & 0 deletions docs/index.mb
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Django Rest Framework - Webhooks
**Configurable webhooks for DRF Serializers**

## Goals:
- [x] Use existing DRF Serializers from REST API to serialize data in webhooks
- [x] Consistent data formatting
- [x] Reusable OpenAPI schemas
- [x] Configurable webhooks that simply work *(by way of django signals magic)* without the developer having to keep track of where to trigger them
- [x] Still allow for "manual" triggering of webhooks
- This is useful because signals aren't always triggered
- For example: `QuerySet.update` does not trigger signals
- [x] Disable webhooks using context managers
- This can be useful when syncing large chunks of data
- or with a duplex sync (when two systems sync with each other) to avoid endless loops
- [x] **Webhook Signal Session**
- [x] A context manager gathers all models signals and at the end of the session only triggers the resulting webhooks
- [x] If a model instance is both `created` and `deleted` within the session, then no webhook is sent for that model instance
- [x] If a model instance is `created` and then also `updated` within the session, then a `created` event is sent with the data from the last `updated` signal. Only one webhook even is sent
- [x] If a models instance is `updated` multiple times within the session, then only one webhook event is sent
- [x] Middleware wraps each request in **Webhook Signal Session** context
- **NOTE:** The developer will have to call the context manager in code that runs outside of requests (for example in celery tasks) manually
- [x] Automatically determine which nested models need to be monitored for changes

## Examples:

```python
from django.db import models
from drf_webhooks import ModelSerializerWebhook, register_webhook
from rest_framework import serializers


class MyModel(models.Model):
name = models.CharField(max_lenght=100)


class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ['id', 'name']


# Automatic:
register_webhook(MyModelSerializer)()

# ---- OR ----
# If you need more configuration:
@register_webhook(MyModelSerializer)
class MyModelWebhook(ModelSerializerWebhook):
base_name = 'core.my_model'
```

# Documentation:

## Quckstart:

### Install `drf-webhooks`
```bash
poetry add drf-webhooks
# ... or ...
pip install drf-webhooks
```

### Update `settings.py`:
```python
INSTALLED_APPS = [
# ...
'drf_webhooks',
]

MIDDLEWARE = [
# ...
'drf_webhooks.middleware.WebhooksMiddleware',
]

# This is required if you don't want your database to fill up with logs:
CELERY_BEAT_SCHEDULE = {
'clean-webhook-log': {
'task': 'drf_webhooks.tasks.auto_clean_log',
'schedule': 60,
'options': {'expires': 10},
},
}
```

### Create a new django app
Recommended app name: `webhooks`

```python
# ----------------------------------------------------------------------
# apps.py
# ----------------------------------------------------------------------
from django.apps import AppConfig


class WebhooksAppConfig(AppConfig):
name = "<your module name>"
label = "webhooks"


# ----------------------------------------------------------------------
# models.py
# ----------------------------------------------------------------------
from django.contrib.auth import get_user_model
from django.db import models
from django.utils.translation import gettext_lazy as _

from drf_webhooks.models import AbstractWebhook, AbstractWebhookLogEntry


class Webhook(AbstractWebhook):
# This can also be a group or an organization that the user belongs to:
owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)

def __str__(self):
return 'id=%s, events=%s, owner=%s' % (
str(self.id),
', '.join(self.events),
str(self.owner),
)


class WebhookLogEntry(AbstractWebhookLogEntry):
# This can also be a group or an organization that the user belongs to:
owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
```
35 changes: 35 additions & 0 deletions docs/make.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)

if "%1" == "" goto help

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%

:end
popd
Loading