Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Plug-in architectures for Python web applications
Search
Raphael Michel
October 25, 2017
Programming
89
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
570
Other Decks in Programming
See All in Programming
APNsからLive Activityを開始する話
yumnumm
0
170
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
28
32k
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
170
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
370
sbt 2.0: takeoff
eed3si9n
0
160
個人開発者よ、Honoを使え(おじさんver)
tanahiro2010
2
260
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
600
golang-bob.pdf
iwatsukayura
0
130
残高管理から台帳サービスへの進化
artoy
1
200
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
5
5.2k
Atomic Design, Enforced: Scaling Mobile Design Systems (next.app devCon / droidCon Berlin 2026)
steliosf
PRO
0
170
ジョジョの世界をXRで再現する
mofurune
0
160
Featured
See All Featured
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
340
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
3.4k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
480
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.3k
How STYLIGHT went responsive
nonsquared
100
6.3k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Product Roadmaps are Hard
iamctodd
55
13k
Scaling GitHub
holman
464
140k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
22k
Automating Front-end Workflow
addyosmani
1369
210k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.5k
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