Pluggable Django Application Patterns PyCon 2011
-
Upload
corey-oordt -
Category
Technology
-
view
6.924 -
download
3
description
Transcript of Pluggable Django Application Patterns PyCon 2011
![Page 1: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/1.jpg)
Pluggable PatternsFor Reusable Django Applications
Friday, March 11, 2011
![Page 2: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/2.jpg)
An app should not be a monolithic pile of code
For example, most blog “apps” available provide too much functionality
MyBlog App• Categories• Custom Tagging• Custom Comments • Comment
Moderation• Assumption of text
markup type• Single blogs• Multiple Sites
ACME MONOLITHS
Friday, March 11, 2011
![Page 3: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/3.jpg)
An application should be “pluggable”
Friday, March 11, 2011
![Page 4: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/4.jpg)
FocusedWrite programs that do one thing and do it well.
— Doug McIlroy (inventor of UNIX pipes)
A “pluggable” app is
Friday, March 11, 2011
![Page 5: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/5.jpg)
Self-ContainedBatteries are included
Dependencies are declared
A “pluggable” app is
Friday, March 11, 2011
![Page 6: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/6.jpg)
Easily AdaptableA “pluggable” app is
Corey’s Law: The less adaptable you make your code, the sooner you will be tasked to adapt it.
Friday, March 11, 2011
![Page 7: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/7.jpg)
Easily InstalledA “pluggable” app is
pip install coolappYou did declare your dependencies, right?
Friday, March 11, 2011
![Page 8: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/8.jpg)
How do we make a “pluggable” application?
Friday, March 11, 2011
![Page 9: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/9.jpg)
Stop thinking like this
http://upload.wikimedia.org/wikipedia/commons/archive/a/aa/20090315161532!Ferrari_Enzo_Ferrari.JPGFriday, March 11, 2011
![Page 10: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/10.jpg)
and think like this
Friday, March 11, 2011
![Page 11: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/11.jpg)
Applications can have very different purposes
http://www.flickr.com/photos/tiemposdelruido/4051083769/Friday, March 11, 2011
![Page 12: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/12.jpg)
Application Types
• Data. Manages specific data and access to itdjango.contrib.auth
• Utility. Provide a way of handling a specific problem for any applicationdjango-pagination, django.contrib.webdesign
• Decorator. Adds functionality to one or aggregates functionality of many applicationsdjango-mptt, django-tagging
Friday, March 11, 2011
![Page 13: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/13.jpg)
Situation 1
You want to configure your app without modifying its code
(e.g. API keys)
Friday, March 11, 2011
![Page 14: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/14.jpg)
Configurable Options
from django.conf import settings
MODULES = getattr(settings, 'SUPERTAGGING_MODULES', {})
Django Supertagging http://github.com/josesoa
Internal Name Setting Name Default Value
Friday, March 11, 2011
![Page 15: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/15.jpg)
Configurable Options
from django.conf import settings
TOOLBAR_CONFIG = { 'INTERCEPT_REDIRECTS': True, 'SHOW_TOOLBAR_CALLBACK': default_show_toolbar, 'EXTRA_SIGNALS': [], 'HIDE_DJANGO_SQL': True, 'SHOW_TEMPLATE_CONTEXT': True, 'TAG': 'body',}
TOOLBAR_CONFIG.update(getattr(settings, 'DEBUG_TOOLBAR_CONFIG', {}))
Django Debug Toolbar http://github.com/robhudson
Friday, March 11, 2011
![Page 16: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/16.jpg)
Data Apps
http://www.flickr.com/photos/29276244@N03/3200630853/Friday, March 11, 2011
![Page 17: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/17.jpg)
Situation 2
Lots of variationsEach implementation is different
(e.g. blogs)
Friday, March 11, 2011
![Page 18: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/18.jpg)
Abstract Models
EntryBase
FeaturableEntryMixin
StatusableEntryMixin
TaggableEntryMixin
HTMLFormattableEntryMixin
GLAMKit http://www.glamkit.org/
class PRBlog(EntryBase, StatusableEntryMixin):
subhead = models.CharField(… pdf = models.FileField(…
Friday, March 11, 2011
![Page 19: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/19.jpg)
Situation 3
A few, well-known of variations(e.g. Use django.contrib.sites?)
Friday, March 11, 2011
![Page 20: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/20.jpg)
Optional Field Settings
from django.db import modelsfrom myapp.settings import MULTIPLE_SITES
if MULTIPLE_SITES: from django.contrib.sites.models import Site
class Entry(models.Model): title = models.CharField(max_length=100) … if MULTIPLE_SITES: sites = models.ManyToManyField(Site)
Friday, March 11, 2011
![Page 21: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/21.jpg)
Situation 4
Optionally use another application
(e.g. Use django-tagging?)
Friday, March 11, 2011
![Page 22: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/22.jpg)
Optional Integration
from django.db import modelsfrom myapp.settings import USE_TAGGING
if USE_TAGGING: from tagging.fields import TagField
class Entry(models.Model): title = models.CharField(max_length=100) … if USE_TAGGING: tags = TagField()
Friday, March 11, 2011
![Page 23: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/23.jpg)
Situation 5
You want to reference different models
(e.g. Customizable author field)
Friday, March 11, 2011
![Page 24: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/24.jpg)
Runtime Configurable Foreign Keys
from django.conf import settingsfrom django.db.models import get_model
model_string = getattr(settings, 'VIEWPOINT_AUTHOR_MODEL', 'auth.User')AUTHOR_MODEL = get_model(*model_string.split('.'))
Viewpoint http://github.com/washingtontimes
Friday, March 11, 2011
![Page 25: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/25.jpg)
Runtime Configurable Foreign Keys
from viewpoint.settings import AUTHOR_MODEL
class Entry(models.Model): title = models.CharField(max_length=100) author = models.ForeignKey(AUTHOR_MODEL) …
Viewpoint http://github.com/washingtontimes
Friday, March 11, 2011
![Page 26: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/26.jpg)
Utility Apps
http://www.flickr.com/photos/s8/3638531205/Friday, March 11, 2011
![Page 27: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/27.jpg)
Required for template tags or
management commands
models.py
Friday, March 11, 2011
![Page 28: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/28.jpg)
Decorator Apps
http://www.flickr.com/photos/yum9me/2109549869/Friday, March 11, 2011
![Page 29: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/29.jpg)
New FieldNew Method
New AdminCustom Manager
Friday, March 11, 2011
![Page 30: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/30.jpg)
Situation 6
You want to add a field to a model
Friday, March 11, 2011
![Page 31: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/31.jpg)
Lazy Field InsertionDjango Categories http://github.com/washingtontimes
Friday, March 11, 2011
![Page 32: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/32.jpg)
Lazy Field Insertion
CATEGORY_FOREIGNKEYS = { 'app1.Model': ('category',) 'app2.Model': ('primary_category', 'secondary_category')}
Django Categories http://github.com/washingtontimes
Friday, March 11, 2011
![Page 33: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/33.jpg)
Lazy Field Insertionfrom django.db.models import get_modelimport django.conf import settings
FOREIGNKEYS = getattr(settings, 'CATEGORY_FOREIGNKEYS', {})
for model_name, cat_fields in FOREIGNKEYS.items(): if not isinstance(model_name, basestring): continue model = get_model(*model_name.split('.')) for category_field in list(cat_fields): try: model._meta.get_field(category_field) except FieldDoesNotExist: ForeignKey(Category).contribute_to_class( model, category_field)
Django Categories http://github.com/washingtontimes
Friday, March 11, 2011
![Page 34: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/34.jpg)
Situation 7
You want to add a custom manager to a model
Friday, March 11, 2011
![Page 35: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/35.jpg)
Lazy Manager Insertion
COOLAPP_MODELS = { 'app1.Model': 'cool_manager', 'app2.Model': 'cool_manager',}
Django MPTT http://github.com/django-mptt
Friday, March 11, 2011
![Page 36: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/36.jpg)
Adding a manager
from django.db.models import get_modelimport django.conf import settingsfrom coolapp.managers import CustomManager
MODELS = getattr(settings, 'COOLAPP_MODELS', {})
for model_name, mgr_name in MODELS.items(): if not isinstance(model_name, basestring): continue model = get_model(*model_name.split('.')) if not getattr(model, mgr_name, False): manager = CustomManager() manager.contribute_to_class(model, mgr_name)
Django MPTT http://github.com/django-mptt
Friday, March 11, 2011
![Page 37: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/37.jpg)
Situation 8
You want to customize a model’s ModelAdmin
(e.g. Change the widget of a field)
Friday, March 11, 2011
![Page 38: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/38.jpg)
Lazy Registration of a Custom ModelAdmin
TINYMCE_ADMIN_FIELDS = { 'app1.model1': ('body',), 'app1.model2': ('blog_text', 'blog_teaser')}
Django TinyMCE http://github.com/justquick
project’s settings.pyFriday, March 11, 2011
![Page 39: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/39.jpg)
Lazy Registration of a Custom ModelAdmin
from django.db.models import get_modelimport django.conf import settings
REGISTRY = {}ADMIN_FIELDS = getattr(settings, 'TINYMCE_ADMIN_FIELDS', {})
for model_name, field in ADMIN_FIELDS.items(): if isinstance(model_name, basestring): model = get_model(*model_name.split('.')) if model in registry: return REGISTRY[model] = field
Django TinyMCE http://github.com/justquick
Django-TinyMCE’s models.pyFriday, March 11, 2011
![Page 40: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/40.jpg)
Lazy Registration of a Custom ModelAdmin
# Define a new ModelAdmin subclass
class TinyMCEAdmin(admin.ModelAdmin): editor_fields = ()
def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name in self.editor_fields: return db_field.formfield(widget=TinyMCE()) return super(TinyMCEAdmin, self).formfield_for_dbfield( db_field, **kwargs)
Django TinyMCE http://github.com/justquick
Django-TinyMCE’s admin.pyFriday, March 11, 2011
![Page 41: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/41.jpg)
Lazy Registration of a Custom ModelAdmin
for model, modeladmin in admin.site._registry.items(): if model in REGISTRY: admin.site.unregister(model) admin.site.register( model, type('newadmin', (TinyMCEAdmin, modeladmin.__class__), {'editor_fields': REGISTRY[model],} ) )
Django TinyMCE http://github.com/justquick
bottom of Django-TinyMCE’s admin.pyFriday, March 11, 2011
![Page 42: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/42.jpg)
Touch Points
Friday, March 11, 2011
![Page 43: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/43.jpg)
Touch Points of an App
The parts of an application that usually need tweaking• URLs• Templates• View responses
Friday, March 11, 2011
![Page 44: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/44.jpg)
Situation 9
You want the URLs of your app to live under any prefix
(e.g. /blogs/ vs. /weblogs/)
Friday, March 11, 2011
![Page 45: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/45.jpg)
Name your URLs
from django.conf.urls.defaults import *
urlpatterns = patterns('', (r'^$', 'coolapp_app.views.index'),)
Friday, March 11, 2011
![Page 46: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/46.jpg)
Name your URLs
from django.conf.urls.defaults import *
urlpatterns = patterns('', url(r'^$', 'coolapp_app.views.index', name='coolapp_index'),)
url Function name
Friday, March 11, 2011
![Page 47: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/47.jpg)
Reference your URLs by name
<p>Go to the <a href="{% url coolapp_index %}">Index</a></p>
from django.core.urlresolvers import reverse
def myview(request): return HttpResponseRedirect(reverse('coolapp_index', args=[]))
Friday, March 11, 2011
![Page 48: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/48.jpg)
Situation 10
You want your templates to be easily overridable
Friday, March 11, 2011
![Page 49: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/49.jpg)
“Namespace” Templates
coolapp
templates
coolapp
All templates in a template
“name space”
base.html
Friday, March 11, 2011
![Page 50: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/50.jpg)
“Namespace” Templates
coolapp
templates
coolapp
Referenced as “coolapp/base.html”
base.html
Friday, March 11, 2011
![Page 51: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/51.jpg)
Extend one template
index.html
base.html
detail.htmlsummary.html
{% extends “base.html” %}
site_base.html
Friday, March 11, 2011
![Page 52: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/52.jpg)
Extend one template
index.html
base.html
detail.htmlsummary.html
{% extends “coolapp/base.html” %}base.html
site_base.html
Friday, March 11, 2011
![Page 53: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/53.jpg)
Extend one template
index.html
base.html
detail.htmlsummary.html
{% extends “coolapp/base.html” %}base.html
site_base.html
Friday, March 11, 2011
![Page 54: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/54.jpg)
Extend one template
coolapp/base.html
{% extends "base.html" %}
{% block head %}{% endblock %}
{% block body %}{% endblock %}
Friday, March 11, 2011
![Page 55: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/55.jpg)
Extend one template
coolapp/base.html
{% extends "base.html" %}
{% block head %}{% endblock %}
{% block body %}{% endblock %}
{% extends "site_base.html" %}
{% block extra_head %} {% block head %} {% endblock %}{% endblock %}
{% block content %} {% block body %} {% endblock %}{% endblock %}
Friday, March 11, 2011
![Page 56: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/56.jpg)
Import your blocks
{% extends "coolapp/base.html" %}
{% block extra_head %} {{ block.super }} {% import "coolapp/extra_head.html" %}{% endblock %}
{% block content %} {# Important content stuff here #}
{% endblock %}
extra_head.html
coolapp/detail.html
Allows you to override any of the templates
Friday, March 11, 2011
![Page 57: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/57.jpg)
Situation 11
You want flexibility storing uploaded files
Friday, March 11, 2011
![Page 58: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/58.jpg)
Define a Storage Optionfrom django.conf import settingsfrom django.core.files.storage import get_storage_class
DEFAULT_STORAGE = get_storage_class(getattr(settings, "MMEDIA_DEFAULT_STORAGE", settings.DEFAULT_FILE_STORAGE)
)
from massmedia.settings import IMAGE_UPLOAD_TO, DEFAULT_STORAGE
class Image(models.Model): file = models.FileField( upload_to = IMAGE_UPLOAD_TO, blank = True, null = True, storage=DEFAULT_STORAGE())
Friday, March 11, 2011
![Page 59: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/59.jpg)
Situation 12
You want to alter the data your views use
(e.g. Extra context, different template)
Friday, March 11, 2011
![Page 60: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/60.jpg)
100% more class-based views!
django-cbv for backwards
compatibility!
Friday, March 11, 2011
![Page 61: Pluggable Django Application Patterns PyCon 2011](https://reader037.fdocuments.us/reader037/viewer/2022102716/5557b7f0d8b42a4a5d8b53b7/html5/thumbnails/61.jpg)
My Info
• @coordt
• github.com/coordt
• github.com/washingtontimes
• opensource.washingtontimes.com
Friday, March 11, 2011