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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
260
Data Internationalization in Django
raphaelm
2
550
Other Decks in Programming
See All in Programming
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.7k
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
280
技術記事、 専門家としてのプログラマ、 言語化
mizchi
13
7.1k
任せる範囲はこう広がった / How the Scope of AI Delegation Has Expanded
nrslib
1
220
技術的負債解消で開発者の未来を開く- AIの力でコード刷新
kmd2kmd
0
130
代数的データ型って何が嬉しいの? #frontend_phpcon_do
kajitack
8
3.8k
OS アップデート対応の取り組み方がもっと共有されてほしい
andpad
0
110
Dataformのリポジトリを立ち上げるときにまずやること / dataform-day0-2026
snhryt
0
200
Javaの型とAI時代に型が大事な理由 / java types and type in AI era
kishida
2
160
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
380
気圧・高度・GPSを記録&可視化するアプリ「Koudo」を作った話
hjmkth
1
330
Webフレームワークの ベンチマークについて
yusukebe
0
190
Featured
See All Featured
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.4k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
870
How to train your dragon (web standard)
notwaldorf
97
6.7k
Six Lessons from altMBA
skipperchong
29
4.3k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
450
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
3.6k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
210
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
610
Navigating Team Friction
lara
192
16k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
630
Statistics for Hackers
jakevdp
799
230k
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