Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Plug-in architectures for Python web applications
Search
Raphael Michel
October 25, 2017
Programming
78
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Plug-in architectures for Python web applications
Raphael Michel
October 25, 2017
More Decks by Raphael Michel
See All by Raphael Michel
Automatic Screenshots of your Django web application with py.test and Selenium
raphaelm
1
270
Data Internationalization in Django
raphaelm
2
560
Other Decks in Programming
See All in Programming
Claude CodeとAgentCore Gatewayを繋ぐ際の認証認可 / Authentication and authorization when connecting Claude Code with AgentCore Gateway
har1101
2
300
Built Our Own Background Agent at LayerX
layerx
PRO
10
5.7k
「人を評価する AI」の設計と実装
ryoyanara
0
210
琵琶湖の水は止められてもNet--HTTPのリトライは止められない / You might be able to stop the water flow of Lake Biwa but you can't stop Net::HTTP retries
luccafort
PRO
0
770
komatsuna「分散システムにおけるバグ分析手法」
komatsunaqa
0
270
freeeにおけるEvalsの実践例の紹介
freee
PRO
0
120
SlackアプリとLambdaの 連携を構築した話
pawn_4_s
1
120
数百円から始めるRuby電子工作
tarosay
0
160
AWS CDK を「作」ってみた 〜フルスクラッチで見えた CDK の裏側〜 / aws-cdk-from-scratch
gotok365
3
2.8k
Japan Community Day at Kubecon + CloudNativeCon Japan 2026: Learning Container Privilege Control by Building My Own Low-Level Container Runtime
ternbusty
1
160
the container ship “Apple Silicon”@WWDC26 Recap -Japan-\(region).swift
shingangan
0
130
Foundation Models frameworkで画像分析
ryodeveloper
1
620
Featured
See All Featured
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
420
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.8k
The Curious Case for Waylosing
cassininazir
1
460
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
What does AI have to do with Human Rights?
axbom
PRO
1
2.3k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
490
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
Visualization
eitanlees
152
17k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
570
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
770
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
420
Transcript
PLUG IN ECOSYSTEMS FOR PYTHON WEB APPLICATIONS
None
Source: w3techs.com WordPress is used by 59.6% of all the
websites whose content management system we know. This is 28.7% of all websites.
None
Open Source event ticket shop Python/Django stack Key design goal:
Be extensible. Don't make people patch or fork it.
IDEAS FOR PLUGINS Payment methods Export formats, ticket layouts Additional
features
OUR PLAN 1. Establish a way that plugins can hook
into your application 2. Provide many of these hooks 3. Document them well 4. There is no step four!
LET'S WRITE SOME PYTHON!
SIMPLE SIGNAL SYSTEM class Signal: def __init__(self): self.receivers = []
def register(self, func): self.receivers.append(func) return func def send(self, *args, **kwargs) return [ func(*args, **kwargs) for func in self.receivers ] user_created = Signal() @user_created.register def plugin_listener(): send_mail()
DJANGO.DISPATCH.SIGNAL Similar API Handles thread-safety for you Caching, weak references,
… → If you're on Django, use this one.
1 PLUGIN = 1 DJANGO APP Plugins can have their
own models Plugins can have their own templates Plugins can have their own static files …
HOW TO INSTALL A PLUGIN Like a django app! Install
package with source code Add to INSTALLED_APPS in settings.py Add url include to urls.py Too many steps! And we don't want to touch code…
ALL WE WANT IST $ pip install pretix-xyz (+ migrations,
maybe)
PLUGIN: __INIT__.PY from django.apps import AppConfig class PluginApp(AppConfig): name =
'xyz' verbose_name = 'XYZ plugin' class PretixPluginMeta: name = 'XYZ plugin' def ready(self): from . import signals default_app_config = 'pretix_xyz.PluginApp'
PLUGIN: SETUP.PY setup( name='pretix-xyz', install_requires=[], packages=find_packages(exclude=['tests', 'tests.*']), include_package_data=True, entry_points={ 'pretix.plugin':
[ 'pretix_xyz=pretix_xyz:PretixPluginMeta' ] } )
APP: SETTINGS.PY from pkg_resources import iter_entry_points for entry_point in iter_entry_points(
group='pretix.plugin', name=None): INSTALLED_APPS.append(entry_point.module_name)
PLUGIN: URLS.PY urlpatterns = [ url(…), … ]
APP: URLS.PY plugin_patterns = [] for app in apps.get_app_configs(): if
hasattr(app, 'PretixPluginMeta'): if importlib.util.find_spec(app.name + '.urls'): urlmod = importlib.import_module( app.name + '.urls') plugin_patterns.append( url('', include((singlurlmod.urlpatterns, app.label))) ) urlpatterns = [ ..., url('', include((plugin_patterns, 'plugins'))) ] {% url "plugins:pretix_xyz:my.url.name" %}
THAT'S OUR PLUGIN SYSTEM!
BONUS: PLUGINS PER CLIENT/USER Custom Signal() subclass Store list of
enabled plugins per client More URL magic (if wanted)
MAKE IT EASY {% load signal %} … {% signal
"pretix.control.signals.order_info" order=order %} @register.simple_tag def signal(signame: str, **kwargs): sigmodule, signame = signame.rsplit('.', 1) sigmodule = importlib.import_module(sigmodule) signal = getattr(sigmodule, signame) html_result = [] for receiver, response in signal.send(event, **kwargs): if response: html_result.append(response) return mark_safe("".join(html_result))
WRITE DOCUMENTATION No, seriously.
PROVIDE A COOKIECUTTER TEMPLATE $ cookiecutter \ https://github.com/pretix/pretix- plugin-cookiecutter
AUTO-INSTALL Naah, better don't.
THANK YOU! ANY QUESTIONS? Raphael Michel
[email protected]
@_rami_ raphaelm pretix.eu
[email protected]
@pretixeu pretix
MAY 23-27TH, 2018 HEIDELBERG, GERMANY 2018.DJANGOCON.EU