SlideShare ist ein Scribd-Unternehmen logo
1 von 30
Downloaden Sie, um offline zu lesen
Five class-based views
everyone has written
by now
James Aylett
artfinder.com
Wednesday, 2 November 11
Django 1.3, released in March, introduced CLASS BASED VIEWS, which are intended to be
make writing views easy and delightful. They replaced the function-based generic views, and
therefore must be better, or something.
from	
  django.views.generic	
  import	
  *
class	
  AWub(DetailView):
	
  	
  model	
  =	
  Wub
class	
  Wubs(ListView):
	
  	
  model	
  =	
  Wub
Wednesday, 2 November 11
We’ll pretend you can’t pass parameters in urlconfs, because that’s icky and also misses the
point.
from	
  django.views.generic	
  import	
  *
class	
  AWub(DetailView):
	
  	
  model	
  =	
  Wub
class	
  Wubs(ListView):
	
  	
  model	
  =	
  Wub
	
  	
  def	
  get_queryset(self):
	
  	
  	
  	
  return	
  Wub.objects.exclude(
	
  	
  	
  	
  	
  	
  hidden=True
	
  	
  	
  	
  )
Wednesday, 2 November 11
The point is that you can override small bits of the ways the views work, to refine them for
your application. Add further context for your templates, change the queryset and so on.
There are conventional places to put templates, and for naming template context members.
Upshot: little code, big effect.
from	
  django.views.generic	
  import	
  *
class	
  NewWub(CreateView):
	
  	
  model	
  =	
  Wub
class	
  DeleteWub(DeleteView):
	
  	
  model	
  =	
  Wub
class	
  UpdateWub(UpdateView):
	
  	
  model	
  =	
  Wub
Wednesday, 2 November 11
Generic views had ways of editing, creating and deleting, so you get that too. Write a suitable
template, and EVERYTHING else is automatic, using a default form. If you want a different
form, you can override that easily enough. Sounds good, right?
Wednesday, 2 November 11
Unfortunately you are about to enter a world of pain. Let’s consider an example that isn’t
completely trivial.
from	
  django.db	
  import	
  models
class	
  WubFlock(models.Model):
	
  	
  name	
  =	
  models.CharField(…)
class	
  Wub(models.Model):
	
  	
  name	
  =	
  models.CharField(…)
	
  	
  flock	
  =	
  models.ForeignKey(
	
  	
  	
  	
  WubFlock,	
  related_name=‘wubs’)
Wednesday, 2 November 11
Okay, so we have a flock of Wubs. We’re building a wub management interface, so we’ll need
to create new wubs within a flock. Except…oh no. You can’t do that.
from	
  django.views.generic	
  import	
  *
class	
  NewFlockWub(CreateView):
	
  	
  model	
  =	
  Wub
	
  	
  #	
  what	
  goes	
  here?
Wednesday, 2 November 11
Okay, so you want to customise the form so it’ll exclude the “flock” field, but set it pre-save
to the flock this wub is going to be in. (Yes you could have a dropdown of all flocks, but then
your designer will murder you in your sleep.)
from	
  django.views.generic	
  import	
  *
class	
  NewFlockWub(CreateView):
	
  	
  model	
  =	
  Wub
	
  	
  form_class	
  =	
  
	
  	
  	
  	
  SomethingSomethingForm
Wednesday, 2 November 11
Okay, so we’ll define the form somewhere. Only…
from	
  django.views.generic	
  import	
  *
class	
  NewFlockWub(CreateView):
	
  	
  model	
  =	
  Wub
	
  	
  form_class	
  =	
  
	
  	
  	
  	
  SomethingSomethingForm
	
  	
  #	
  erm,	
  but	
  we	
  need	
  to	
  get
	
  	
  #	
  the	
  flock	
  object	
  for	
  the	
  form
Wednesday, 2 November 11
You want to figure out the flock from the URL, say “/flock/my-awesome-wubs”. DetailView
does this, and like all class-based views is built up of composable little pieces, so you could
bring in SingleObjectMixin, which provides get_object to do this. Then we could override
get_form_class to set up the form dynamically. But this behaviour is generic, so…
from	
  moreviews	
  import	
  *
class	
  NewFlockWub(BoundCreateView):
	
  	
  model	
  =	
  Wub
	
  	
  bound_field	
  =	
  ‘flock’
	
  	
  queryset	
  =	
  WubFlock.objects.all()
Wednesday, 2 November 11
If your BoundCreateView isn’t this easy, you’re doing it wrong. “Bound” because the Wub is
bound to the WubFlock.
class	
  DeleteWub(DeleteView):
	
  	
  model	
  =	
  Wub
class	
  F(forms.ModelForm):
	
  	
  class	
  Meta:
	
  	
  	
  	
  model	
  =	
  Wub
	
  	
  	
  	
  exclude	
  =	
  (‘flock’,)
class	
  UpdateWub(UpdateView):
	
  	
  model	
  =	
  Wub
	
  	
  form_class	
  =	
  F
Wednesday, 2 November 11
We don’t have to worry about binding for deleting, and for updating we just ensure we don’t
change the “flock” field.
Wednesday, 2 November 11
But what about the WubFlock? We should be able to create it AND ITS WUBS in one go. In
traditional function views you’d do this with forms and formsets within the same request. So
we want to do the same thing in class-based views.
class	
  ProcessMultipleFormsMixin:
	
  	
  """Modify	
  GET	
  and	
  POST	
  behaviour	
  
to	
  construct	
  and	
  process	
  multiple	
  
forms	
  in	
  one	
  go.	
  There's	
  always	
  a	
  
primary	
  form,	
  which	
  is	
  a	
  ModelForm.
By	
  the	
  time	
  secondary	
  forms	
  are	
  
saved,	
  self.new_object	
  on	
  the	
  view	
  
will	
  contain	
  the	
  primary	
  object,	
  ie	
  
the	
  object	
  that	
  the	
  primary	
  form	
  
operates	
  on."""
Wednesday, 2 November 11
This isn’t one of the five classes, this is just a mixin. It’s not named perfectly, because
although it DOES process multiple forms at once, it assumes one is the main form. This
allows us to save the PRINCIPAL object, and then leaves a reference for all the other forms to
use.
from	
  django.views.generic	
  import	
  *
class	
  NewFlock(MultiCreateView):
	
  	
  model	
  =	
  WubFlock
	
  	
  forms_models	
  =	
  [
	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  ‘model’:	
  Wub,
	
  	
  	
  	
  	
  	
  ‘extra’:	
  1,
	
  	
  	
  	
  }
	
  	
  ]
Wednesday, 2 November 11
This syntax is a little opaque, but it didn’t seem worth creating yet more classes just as
helpers when we have lists and dictionaries. The exclude of the project field in the
ModelForm for making little Wubs is taken care of for you.
from	
  django.views.generic	
  import	
  *
class	
  UpdateFlock(MultiUpdateView):
	
  	
  model	
  =	
  WubFlock
	
  	
  forms_models	
  =	
  [
	
  	
  	
  	
  {
	
  	
  	
  	
  	
  	
  ‘model’:	
  Wub,
	
  	
  	
  	
  	
  	
  ‘extra’:	
  1,
	
  	
  	
  	
  	
  	
  ‘can_delete’:	
  True,
	
  	
  	
  	
  }
	
  	
  ]
Wednesday, 2 November 11
extra and can_delete here are both passed through to modelformset_factory. You can also set
form inside the dictionary so you don’t just get a default ModelForm but can customise to
your heart’s content.
from	
  django.views.generic	
  import	
  *
class	
  UpdateFlock(MultiUpdateView):
	
  	
  …
	
  	
  def	
  get_forms(self):
	
  	
  	
  	
  class	
  WubInlineForm(ModelForm):
	
  	
  	
  	
  	
  	
  def	
  save(self):
	
  	
  	
  	
  	
  	
  	
  	
  #	
  perhaps	
  we	
  default	
  the	
  
	
  	
  	
  	
  	
  	
  	
  	
  #	
  name	
  based	
  on	
  the	
  flock?
	
  	
  	
  	
  self.forms_models[0][‘form’]	
  
	
  	
  	
  	
  	
  	
  =	
  WubInlineForm
	
  	
  	
  	
  return	
  super(...)()
Wednesday, 2 November 11
You can even dynamically adjust things if you so choose. In fact, you can avoid forms_models
by implementing get_forms directly if you prefer.
from	
  django.views.generic	
  import	
  *
class	
  DeleteFlock(DeleteView):
	
  	
  model	
  =	
  WubFlock
Wednesday, 2 November 11
And of course deleting a flock will delete its wubs via the evil of the ORM’s implementing
CASCADE DELETE itself.
Wednesday, 2 November 11
There’s also a variant which will allow you to create an object bound to another but which
itself has children bound to it. It’s imaginatively called MultiBoundCreateView. That’s not one
of the five, that’s a bonus one. However now we need to think about non-editing views again,
because we’ve still got a problem.
from	
  django.views.generic	
  import	
  *
class	
  Wubs(ListView):
	
  	
  model	
  =	
  Wub
class	
  Flock(DetailView):
	
  	
  model	
  =	
  WubFlock
Wednesday, 2 November 11
This is fine until you have a flock with three thousand wubs in. And wubs are very gregarious.
from	
  django.views.generic	
  import	
  *
class	
  Wubs(ListView):
	
  	
  model	
  =	
  Wub
	
  	
  paginate_by	
  =	
  10
class	
  Flock(DetailView):
	
  	
  model	
  =	
  WubFlock
Wednesday, 2 November 11
ListView has pagination built in. Wouldn’t it be nice if we could do that for the CHILDREN
bound to the object in a DetailView?
from	
  django.views.generic	
  import	
  *
from	
  moreviews	
  import	
  *
class	
  Wubs(ListView):
	
  	
  model	
  =	
  Wub
	
  	
  paginate_by	
  =	
  10
class	
  Flock(DetailListView):
	
  	
  model	
  =	
  WubFlock
	
  	
  paginate_by	
  =	
  10
Wednesday, 2 November 11
This is the fourth view. Warning: this exists, deep within the Artfinder codebase, but isn’t re-
usable yet.
Wednesday, 2 November 11
We’re not finished yet.
From:	
  Your	
  Boss	
  <phb@myco.co.com>
To:	
  You	
  <peon@myco.co.com>
Subject:	
  Permissions
Yo	
  dawg.	
  I	
  was	
  over	
  at	
  Big	
  Client	
  
Co	
  this	
  morning	
  and	
  noticed	
  that	
  
they’re	
  able	
  to	
  edit	
  the	
  WubFlock	
  
for	
  the	
  Sinister	
  Government	
  
Agency.	
  This	
  contains	
  proprietary	
  
Wub	
  technology,	
  and	
  geese,	
  so	
  THIS	
  
SHOULD	
  NOT	
  BE	
  ALLOWED.
Wednesday, 2 November 11
Maybe your site allows everyone to see and do everything. Most don’t. What you used to do
with function views was to check the permission at the top of the view and return a 403. In
class-based views you need to do that around get_object, which gives you direct access to
the object.
def	
  editable():
	
  	
  def	
  decorator(fn):
	
  	
  	
  	
  @wraps(fn,	
  assigned=available_attrs(fn))
	
  	
  	
  	
  def	
  _wrapped_fn(self,	
  *args,	
  **kwargs):
	
  	
  	
  	
  	
  	
  obj	
  =	
  fn(self,	
  *args,	
  **kwargs)
	
  	
  	
  	
  	
  	
  if	
  obj.editable(self.request.user):
	
  	
  	
  	
  	
  	
  	
  	
  return	
  obj
	
  	
  	
  	
  	
  	
  else:
	
  	
  	
  	
  	
  	
  	
  	
  raise	
  HttpForbidden()
	
  	
  	
  	
  return	
  _wrapped_fn
	
  	
  return	
  decorator
class	
  _UpdateFlock(UpdateFlock):
	
  	
  get_object	
  =	
  
	
  	
  	
  	
  editable(UpdateFlock.get_object)
Wednesday, 2 November 11
Oh god oh god I want to die. Ignore that decorators make most people’s heads hurt, just
LOOK AT THAT CODE AT THE BOTTOM.
class	
  _UpdateFlock(UpdateFlock):
	
  	
  get_object	
  =	
  
	
  	
  	
  	
  editable(
	
  	
  	
  	
  	
  	
  UpdateFlock.get_object
	
  	
  	
  	
  )
Wednesday, 2 November 11
There is no way this is going to look nice, no matter how many lines we wrap it onto. So this
is the fifth class…that I’m really hoping someone has written. I want to write something like
the following.
class	
  _UpdateFlock(UpdateFlock):
	
  	
  def	
  allowed(self):
	
  	
  	
  	
  return	
  self.object.editable(
	
  	
  	
  	
  	
  	
  self.request.user
	
  	
  	
  	
  )
Wednesday, 2 November 11
Which is basically the same but not ugly. I guess what we actually want here is a permissions-
activating mixin.
class	
  _UpdateFlock(
	
  	
  UpdateFlock,
	
  	
  SingleObjectPermissionsMixin):
	
  	
  def	
  allowed(self):
	
  	
  	
  	
  return	
  self.object.editable(
	
  	
  	
  	
  	
  	
  self.request.user
	
  	
  	
  	
  )
Wednesday, 2 November 11
class	
  SingleObjectPermissionsMixin(
	
  	
  object):
	
  	
  def	
  get_object(self):
	
  	
  	
  	
  obj	
  =	
  super(
	
  	
  	
  	
  	
  	
  SingleObjectPermissionsMixin,
	
  	
  	
  	
  	
  	
  self).get_object()
	
  	
  	
  	
  if	
  not	
  self.allowed(obj):
	
  	
  	
  	
  	
  	
  raise	
  HttpForbidden()
	
  	
  	
  	
  return	
  obj
	
  	
  def	
  allowed(self):
	
  	
  	
  	
  raise	
  NotImplementedError()
Wednesday, 2 November 11
So this would be the fifth class. I haven’t written this, but I assume someone has. I suspect as
I have it here, there are lots of problems, not least that HttpForbidden doesn’t exist in Django
itself and so you’re dependent on something else to not only provide it but catch it in
middleware and do something sensible with it.
Summary
• BoundCreateView for making Wubs
• MultiCreateView for making WubFlocks
• MultiUpdateView to update WubFlocks
• DetailListView for paginating child objects
• SingleObjectPermissionsMixin is mythical
Wednesday, 2 November 11
The first three are written, but Ben caught me by surprise by asking me to talk, so they aren’t
packaged and they’re not directly tested. DetailListView needs extracting from well-used
internal code. The permissions stuff is entirely speculative; maybe we don’t need it.
Questions?
• James Aylett
• @jaylett
• artfinder.com
• http://bit.ly/djugl-art
Wednesday, 2 November 11

Weitere ähnliche Inhalte

Was ist angesagt?

Grain final border one
Grain final border oneGrain final border one
Grain final border oneAshish Gupta
 
Javascript Module Patterns
Javascript Module PatternsJavascript Module Patterns
Javascript Module PatternsNicholas Jansma
 
From YUI3 to K2
From YUI3 to K2From YUI3 to K2
From YUI3 to K2kaven yan
 
Introduction to Design Patterns in Javascript
Introduction to Design Patterns in JavascriptIntroduction to Design Patterns in Javascript
Introduction to Design Patterns in JavascriptSanthosh Kumar Srinivasan
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersDavid Rodenas
 
JavaScript Modules Done Right
JavaScript Modules Done RightJavaScript Modules Done Right
JavaScript Modules Done RightMariusz Nowak
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing UpDavid Padbury
 
Overlays, Accordions & Tabs, Oh My
Overlays, Accordions & Tabs, Oh MyOverlays, Accordions & Tabs, Oh My
Overlays, Accordions & Tabs, Oh MySteve McMahon
 
Patterns for JVM languages - Geecon 2014
Patterns for JVM languages - Geecon 2014Patterns for JVM languages - Geecon 2014
Patterns for JVM languages - Geecon 2014Jaroslaw Palka
 
Creational pattern 2
Creational pattern 2Creational pattern 2
Creational pattern 2Naga Muruga
 
Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]Aaron Gustafson
 
JavaScript Best Pratices
JavaScript Best PraticesJavaScript Best Pratices
JavaScript Best PraticesChengHui Weng
 
Javascript Prototype Visualized
Javascript Prototype VisualizedJavascript Prototype Visualized
Javascript Prototype Visualized军 沈
 
Large-Scale JavaScript Development
Large-Scale JavaScript DevelopmentLarge-Scale JavaScript Development
Large-Scale JavaScript DevelopmentAddy Osmani
 
Spring 3.0 dependancy injection
Spring 3.0 dependancy injectionSpring 3.0 dependancy injection
Spring 3.0 dependancy injectionRajiv Gupta
 

Was ist angesagt? (20)

Grain final border one
Grain final border oneGrain final border one
Grain final border one
 
JavaScript Patterns
JavaScript PatternsJavaScript Patterns
JavaScript Patterns
 
Javascript Design Patterns
Javascript Design PatternsJavascript Design Patterns
Javascript Design Patterns
 
Patterns In-Javascript
Patterns In-JavascriptPatterns In-Javascript
Patterns In-Javascript
 
Javascript Module Patterns
Javascript Module PatternsJavascript Module Patterns
Javascript Module Patterns
 
From YUI3 to K2
From YUI3 to K2From YUI3 to K2
From YUI3 to K2
 
Introduction to Design Patterns in Javascript
Introduction to Design Patterns in JavascriptIntroduction to Design Patterns in Javascript
Introduction to Design Patterns in Javascript
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
 
JavaScript Modules Done Right
JavaScript Modules Done RightJavaScript Modules Done Right
JavaScript Modules Done Right
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
Overlays, Accordions & Tabs, Oh My
Overlays, Accordions & Tabs, Oh MyOverlays, Accordions & Tabs, Oh My
Overlays, Accordions & Tabs, Oh My
 
Patterns for JVM languages - Geecon 2014
Patterns for JVM languages - Geecon 2014Patterns for JVM languages - Geecon 2014
Patterns for JVM languages - Geecon 2014
 
Creational pattern 2
Creational pattern 2Creational pattern 2
Creational pattern 2
 
Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]
 
JavaScript Best Pratices
JavaScript Best PraticesJavaScript Best Pratices
JavaScript Best Pratices
 
Using java beans(ii)
Using java beans(ii)Using java beans(ii)
Using java beans(ii)
 
Javascript Best Practices
Javascript Best PracticesJavascript Best Practices
Javascript Best Practices
 
Javascript Prototype Visualized
Javascript Prototype VisualizedJavascript Prototype Visualized
Javascript Prototype Visualized
 
Large-Scale JavaScript Development
Large-Scale JavaScript DevelopmentLarge-Scale JavaScript Development
Large-Scale JavaScript Development
 
Spring 3.0 dependancy injection
Spring 3.0 dependancy injectionSpring 3.0 dependancy injection
Spring 3.0 dependancy injection
 

Ähnlich wie Five class-based views everyone has written by now

My Favourite 10 Things about Xcode/ObjectiveC
My Favourite 10 Things about Xcode/ObjectiveCMy Favourite 10 Things about Xcode/ObjectiveC
My Favourite 10 Things about Xcode/ObjectiveCJohnKennedy
 
Reusable Ruby • Rt 9 Ruby Group • Jun 2012
Reusable Ruby • Rt 9 Ruby Group • Jun 2012Reusable Ruby • Rt 9 Ruby Group • Jun 2012
Reusable Ruby • Rt 9 Ruby Group • Jun 2012skinandbones
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfShaiAlmog1
 
Backbone beyond jQuery
Backbone beyond jQueryBackbone beyond jQuery
Backbone beyond jQueryAdam Krebs
 
Jquery Plugin
Jquery PluginJquery Plugin
Jquery PluginRavi Mone
 
Unbundling the JavaScript module bundler - DublinJS July 2018
Unbundling the JavaScript module bundler - DublinJS July 2018Unbundling the JavaScript module bundler - DublinJS July 2018
Unbundling the JavaScript module bundler - DublinJS July 2018Luciano Mammino
 
Objective C Block
Objective C BlockObjective C Block
Objective C BlockFantageek
 
Memory management in Objective C
Memory management in Objective CMemory management in Objective C
Memory management in Objective CNeha Gupta
 
Intro to Angular.JS Directives
Intro to Angular.JS DirectivesIntro to Angular.JS Directives
Intro to Angular.JS DirectivesChristian Lilley
 
Learn jobDSL for Jenkins
Learn jobDSL for JenkinsLearn jobDSL for Jenkins
Learn jobDSL for JenkinsLarry Cai
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyDavid Padbury
 
Gitter marionette deck
Gitter marionette deckGitter marionette deck
Gitter marionette deckMike Bartlett
 
The Future of the Web
The Future of the WebThe Future of the Web
The Future of the WebRay Nicholus
 

Ähnlich wie Five class-based views everyone has written by now (20)

My Favourite 10 Things about Xcode/ObjectiveC
My Favourite 10 Things about Xcode/ObjectiveCMy Favourite 10 Things about Xcode/ObjectiveC
My Favourite 10 Things about Xcode/ObjectiveC
 
Reusable Ruby • Rt 9 Ruby Group • Jun 2012
Reusable Ruby • Rt 9 Ruby Group • Jun 2012Reusable Ruby • Rt 9 Ruby Group • Jun 2012
Reusable Ruby • Rt 9 Ruby Group • Jun 2012
 
Fork cli tool
Fork cli toolFork cli tool
Fork cli tool
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
 
Backbone beyond jQuery
Backbone beyond jQueryBackbone beyond jQuery
Backbone beyond jQuery
 
Knockoutjs
KnockoutjsKnockoutjs
Knockoutjs
 
Jquery Plugin
Jquery PluginJquery Plugin
Jquery Plugin
 
Unbundling the JavaScript module bundler - DublinJS July 2018
Unbundling the JavaScript module bundler - DublinJS July 2018Unbundling the JavaScript module bundler - DublinJS July 2018
Unbundling the JavaScript module bundler - DublinJS July 2018
 
Objective C Block
Objective C BlockObjective C Block
Objective C Block
 
Memory management in Objective C
Memory management in Objective CMemory management in Objective C
Memory management in Objective C
 
Intro to Angular.JS Directives
Intro to Angular.JS DirectivesIntro to Angular.JS Directives
Intro to Angular.JS Directives
 
Learn jobDSL for Jenkins
Learn jobDSL for JenkinsLearn jobDSL for Jenkins
Learn jobDSL for Jenkins
 
Doc abap
Doc abapDoc abap
Doc abap
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
Gitter marionette deck
Gitter marionette deckGitter marionette deck
Gitter marionette deck
 
Backbonejs
BackbonejsBackbonejs
Backbonejs
 
Testable Javascript
Testable JavascriptTestable Javascript
Testable Javascript
 
Introduction Php
Introduction PhpIntroduction Php
Introduction Php
 
Oojs 1.1
Oojs 1.1Oojs 1.1
Oojs 1.1
 
The Future of the Web
The Future of the WebThe Future of the Web
The Future of the Web
 

Mehr von James Aylett

Git, from the beginning
Git, from the beginningGit, from the beginning
Git, from the beginningJames Aylett
 
Django Files — A Short Talk (slides only)
Django Files — A Short Talk (slides only)Django Files — A Short Talk (slides only)
Django Files — A Short Talk (slides only)James Aylett
 
IA Isn't New, or: What would Samuel Pepys' website look like?
IA Isn't New, or: What would Samuel Pepys' website look like?IA Isn't New, or: What would Samuel Pepys' website look like?
IA Isn't New, or: What would Samuel Pepys' website look like?James Aylett
 
Django Files — A Short Talk
Django Files — A Short TalkDjango Files — A Short Talk
Django Files — A Short TalkJames Aylett
 
On committing well
On committing wellOn committing well
On committing wellJames Aylett
 
/dev/fort: you can build it in a week @emw
/dev/fort: you can build it in a week @emw/dev/fort: you can build it in a week @emw
/dev/fort: you can build it in a week @emwJames Aylett
 
Accessible by Voice
Accessible by VoiceAccessible by Voice
Accessible by VoiceJames Aylett
 
Spacelog: things we did right-ish
Spacelog: things we did right-ishSpacelog: things we did right-ish
Spacelog: things we did right-ishJames Aylett
 

Mehr von James Aylett (11)

Git, from the beginning
Git, from the beginningGit, from the beginning
Git, from the beginning
 
Django Files — A Short Talk (slides only)
Django Files — A Short Talk (slides only)Django Files — A Short Talk (slides only)
Django Files — A Short Talk (slides only)
 
IA Isn't New, or: What would Samuel Pepys' website look like?
IA Isn't New, or: What would Samuel Pepys' website look like?IA Isn't New, or: What would Samuel Pepys' website look like?
IA Isn't New, or: What would Samuel Pepys' website look like?
 
Django Files — A Short Talk
Django Files — A Short TalkDjango Files — A Short Talk
Django Files — A Short Talk
 
Beyond blockers
Beyond blockersBeyond blockers
Beyond blockers
 
Tree surgery
Tree surgeryTree surgery
Tree surgery
 
On committing well
On committing wellOn committing well
On committing well
 
/dev/fort: you can build it in a week @emw
/dev/fort: you can build it in a week @emw/dev/fort: you can build it in a week @emw
/dev/fort: you can build it in a week @emw
 
Accessible by Voice
Accessible by VoiceAccessible by Voice
Accessible by Voice
 
Spacelog: things we did right-ish
Spacelog: things we did right-ishSpacelog: things we did right-ish
Spacelog: things we did right-ish
 
Web heresies
Web heresiesWeb heresies
Web heresies
 

Kürzlich hochgeladen

How To Simplify Your Scheduling with AI Calendarfly The Hassle-Free Online Bo...
How To Simplify Your Scheduling with AI Calendarfly The Hassle-Free Online Bo...How To Simplify Your Scheduling with AI Calendarfly The Hassle-Free Online Bo...
How To Simplify Your Scheduling with AI Calendarfly The Hassle-Free Online Bo...SOFTTECHHUB
 
WSMM Media and Entertainment Feb_March_Final.pdf
WSMM Media and Entertainment Feb_March_Final.pdfWSMM Media and Entertainment Feb_March_Final.pdf
WSMM Media and Entertainment Feb_March_Final.pdfJamesConcepcion7
 
TriStar Gold Corporate Presentation - April 2024
TriStar Gold Corporate Presentation - April 2024TriStar Gold Corporate Presentation - April 2024
TriStar Gold Corporate Presentation - April 2024Adnet Communications
 
GUIDELINES ON USEFUL FORMS IN FREIGHT FORWARDING (F) Danny Diep Toh MBA.pdf
GUIDELINES ON USEFUL FORMS IN FREIGHT FORWARDING (F) Danny Diep Toh MBA.pdfGUIDELINES ON USEFUL FORMS IN FREIGHT FORWARDING (F) Danny Diep Toh MBA.pdf
GUIDELINES ON USEFUL FORMS IN FREIGHT FORWARDING (F) Danny Diep Toh MBA.pdfDanny Diep To
 
BAILMENT & PLEDGE business law notes.pptx
BAILMENT & PLEDGE business law notes.pptxBAILMENT & PLEDGE business law notes.pptx
BAILMENT & PLEDGE business law notes.pptxran17april2001
 
Lucia Ferretti, Lead Business Designer; Matteo Meschini, Business Designer @T...
Lucia Ferretti, Lead Business Designer; Matteo Meschini, Business Designer @T...Lucia Ferretti, Lead Business Designer; Matteo Meschini, Business Designer @T...
Lucia Ferretti, Lead Business Designer; Matteo Meschini, Business Designer @T...Associazione Digital Days
 
PSCC - Capability Statement Presentation
PSCC - Capability Statement PresentationPSCC - Capability Statement Presentation
PSCC - Capability Statement PresentationAnamaria Contreras
 
business environment micro environment macro environment.pptx
business environment micro environment macro environment.pptxbusiness environment micro environment macro environment.pptx
business environment micro environment macro environment.pptxShruti Mittal
 
Guide Complete Set of Residential Architectural Drawings PDF
Guide Complete Set of Residential Architectural Drawings PDFGuide Complete Set of Residential Architectural Drawings PDF
Guide Complete Set of Residential Architectural Drawings PDFChandresh Chudasama
 
1911 Gold Corporate Presentation Apr 2024.pdf
1911 Gold Corporate Presentation Apr 2024.pdf1911 Gold Corporate Presentation Apr 2024.pdf
1911 Gold Corporate Presentation Apr 2024.pdfShaun Heinrichs
 
Onemonitar Android Spy App Features: Explore Advanced Monitoring Capabilities
Onemonitar Android Spy App Features: Explore Advanced Monitoring CapabilitiesOnemonitar Android Spy App Features: Explore Advanced Monitoring Capabilities
Onemonitar Android Spy App Features: Explore Advanced Monitoring CapabilitiesOne Monitar
 
1911 Gold Corporate Presentation Apr 2024.pdf
1911 Gold Corporate Presentation Apr 2024.pdf1911 Gold Corporate Presentation Apr 2024.pdf
1911 Gold Corporate Presentation Apr 2024.pdfShaun Heinrichs
 
Jewish Resources in the Family Resource Centre
Jewish Resources in the Family Resource CentreJewish Resources in the Family Resource Centre
Jewish Resources in the Family Resource CentreNZSG
 
Appkodes Tinder Clone Script with Customisable Solutions.pptx
Appkodes Tinder Clone Script with Customisable Solutions.pptxAppkodes Tinder Clone Script with Customisable Solutions.pptx
Appkodes Tinder Clone Script with Customisable Solutions.pptxappkodes
 
Traction part 2 - EOS Model JAX Bridges.
Traction part 2 - EOS Model JAX Bridges.Traction part 2 - EOS Model JAX Bridges.
Traction part 2 - EOS Model JAX Bridges.Anamaria Contreras
 
WSMM Technology February.March Newsletter_vF.pdf
WSMM Technology February.March Newsletter_vF.pdfWSMM Technology February.March Newsletter_vF.pdf
WSMM Technology February.March Newsletter_vF.pdfJamesConcepcion7
 
Fordham -How effective decision-making is within the IT department - Analysis...
Fordham -How effective decision-making is within the IT department - Analysis...Fordham -How effective decision-making is within the IT department - Analysis...
Fordham -How effective decision-making is within the IT department - Analysis...Peter Ward
 
Cyber Security Training in Office Environment
Cyber Security Training in Office EnvironmentCyber Security Training in Office Environment
Cyber Security Training in Office Environmentelijahj01012
 
Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...
Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...
Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...ssuserf63bd7
 
Introducing the Analogic framework for business planning applications
Introducing the Analogic framework for business planning applicationsIntroducing the Analogic framework for business planning applications
Introducing the Analogic framework for business planning applicationsKnowledgeSeed
 

Kürzlich hochgeladen (20)

How To Simplify Your Scheduling with AI Calendarfly The Hassle-Free Online Bo...
How To Simplify Your Scheduling with AI Calendarfly The Hassle-Free Online Bo...How To Simplify Your Scheduling with AI Calendarfly The Hassle-Free Online Bo...
How To Simplify Your Scheduling with AI Calendarfly The Hassle-Free Online Bo...
 
WSMM Media and Entertainment Feb_March_Final.pdf
WSMM Media and Entertainment Feb_March_Final.pdfWSMM Media and Entertainment Feb_March_Final.pdf
WSMM Media and Entertainment Feb_March_Final.pdf
 
TriStar Gold Corporate Presentation - April 2024
TriStar Gold Corporate Presentation - April 2024TriStar Gold Corporate Presentation - April 2024
TriStar Gold Corporate Presentation - April 2024
 
GUIDELINES ON USEFUL FORMS IN FREIGHT FORWARDING (F) Danny Diep Toh MBA.pdf
GUIDELINES ON USEFUL FORMS IN FREIGHT FORWARDING (F) Danny Diep Toh MBA.pdfGUIDELINES ON USEFUL FORMS IN FREIGHT FORWARDING (F) Danny Diep Toh MBA.pdf
GUIDELINES ON USEFUL FORMS IN FREIGHT FORWARDING (F) Danny Diep Toh MBA.pdf
 
BAILMENT & PLEDGE business law notes.pptx
BAILMENT & PLEDGE business law notes.pptxBAILMENT & PLEDGE business law notes.pptx
BAILMENT & PLEDGE business law notes.pptx
 
Lucia Ferretti, Lead Business Designer; Matteo Meschini, Business Designer @T...
Lucia Ferretti, Lead Business Designer; Matteo Meschini, Business Designer @T...Lucia Ferretti, Lead Business Designer; Matteo Meschini, Business Designer @T...
Lucia Ferretti, Lead Business Designer; Matteo Meschini, Business Designer @T...
 
PSCC - Capability Statement Presentation
PSCC - Capability Statement PresentationPSCC - Capability Statement Presentation
PSCC - Capability Statement Presentation
 
business environment micro environment macro environment.pptx
business environment micro environment macro environment.pptxbusiness environment micro environment macro environment.pptx
business environment micro environment macro environment.pptx
 
Guide Complete Set of Residential Architectural Drawings PDF
Guide Complete Set of Residential Architectural Drawings PDFGuide Complete Set of Residential Architectural Drawings PDF
Guide Complete Set of Residential Architectural Drawings PDF
 
1911 Gold Corporate Presentation Apr 2024.pdf
1911 Gold Corporate Presentation Apr 2024.pdf1911 Gold Corporate Presentation Apr 2024.pdf
1911 Gold Corporate Presentation Apr 2024.pdf
 
Onemonitar Android Spy App Features: Explore Advanced Monitoring Capabilities
Onemonitar Android Spy App Features: Explore Advanced Monitoring CapabilitiesOnemonitar Android Spy App Features: Explore Advanced Monitoring Capabilities
Onemonitar Android Spy App Features: Explore Advanced Monitoring Capabilities
 
1911 Gold Corporate Presentation Apr 2024.pdf
1911 Gold Corporate Presentation Apr 2024.pdf1911 Gold Corporate Presentation Apr 2024.pdf
1911 Gold Corporate Presentation Apr 2024.pdf
 
Jewish Resources in the Family Resource Centre
Jewish Resources in the Family Resource CentreJewish Resources in the Family Resource Centre
Jewish Resources in the Family Resource Centre
 
Appkodes Tinder Clone Script with Customisable Solutions.pptx
Appkodes Tinder Clone Script with Customisable Solutions.pptxAppkodes Tinder Clone Script with Customisable Solutions.pptx
Appkodes Tinder Clone Script with Customisable Solutions.pptx
 
Traction part 2 - EOS Model JAX Bridges.
Traction part 2 - EOS Model JAX Bridges.Traction part 2 - EOS Model JAX Bridges.
Traction part 2 - EOS Model JAX Bridges.
 
WSMM Technology February.March Newsletter_vF.pdf
WSMM Technology February.March Newsletter_vF.pdfWSMM Technology February.March Newsletter_vF.pdf
WSMM Technology February.March Newsletter_vF.pdf
 
Fordham -How effective decision-making is within the IT department - Analysis...
Fordham -How effective decision-making is within the IT department - Analysis...Fordham -How effective decision-making is within the IT department - Analysis...
Fordham -How effective decision-making is within the IT department - Analysis...
 
Cyber Security Training in Office Environment
Cyber Security Training in Office EnvironmentCyber Security Training in Office Environment
Cyber Security Training in Office Environment
 
Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...
Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...
Intermediate Accounting, Volume 2, 13th Canadian Edition by Donald E. Kieso t...
 
Introducing the Analogic framework for business planning applications
Introducing the Analogic framework for business planning applicationsIntroducing the Analogic framework for business planning applications
Introducing the Analogic framework for business planning applications
 

Five class-based views everyone has written by now

  • 1. Five class-based views everyone has written by now James Aylett artfinder.com Wednesday, 2 November 11 Django 1.3, released in March, introduced CLASS BASED VIEWS, which are intended to be make writing views easy and delightful. They replaced the function-based generic views, and therefore must be better, or something.
  • 2. from  django.views.generic  import  * class  AWub(DetailView):    model  =  Wub class  Wubs(ListView):    model  =  Wub Wednesday, 2 November 11 We’ll pretend you can’t pass parameters in urlconfs, because that’s icky and also misses the point.
  • 3. from  django.views.generic  import  * class  AWub(DetailView):    model  =  Wub class  Wubs(ListView):    model  =  Wub    def  get_queryset(self):        return  Wub.objects.exclude(            hidden=True        ) Wednesday, 2 November 11 The point is that you can override small bits of the ways the views work, to refine them for your application. Add further context for your templates, change the queryset and so on. There are conventional places to put templates, and for naming template context members. Upshot: little code, big effect.
  • 4. from  django.views.generic  import  * class  NewWub(CreateView):    model  =  Wub class  DeleteWub(DeleteView):    model  =  Wub class  UpdateWub(UpdateView):    model  =  Wub Wednesday, 2 November 11 Generic views had ways of editing, creating and deleting, so you get that too. Write a suitable template, and EVERYTHING else is automatic, using a default form. If you want a different form, you can override that easily enough. Sounds good, right?
  • 5. Wednesday, 2 November 11 Unfortunately you are about to enter a world of pain. Let’s consider an example that isn’t completely trivial.
  • 6. from  django.db  import  models class  WubFlock(models.Model):    name  =  models.CharField(…) class  Wub(models.Model):    name  =  models.CharField(…)    flock  =  models.ForeignKey(        WubFlock,  related_name=‘wubs’) Wednesday, 2 November 11 Okay, so we have a flock of Wubs. We’re building a wub management interface, so we’ll need to create new wubs within a flock. Except…oh no. You can’t do that.
  • 7. from  django.views.generic  import  * class  NewFlockWub(CreateView):    model  =  Wub    #  what  goes  here? Wednesday, 2 November 11 Okay, so you want to customise the form so it’ll exclude the “flock” field, but set it pre-save to the flock this wub is going to be in. (Yes you could have a dropdown of all flocks, but then your designer will murder you in your sleep.)
  • 8. from  django.views.generic  import  * class  NewFlockWub(CreateView):    model  =  Wub    form_class  =          SomethingSomethingForm Wednesday, 2 November 11 Okay, so we’ll define the form somewhere. Only…
  • 9. from  django.views.generic  import  * class  NewFlockWub(CreateView):    model  =  Wub    form_class  =          SomethingSomethingForm    #  erm,  but  we  need  to  get    #  the  flock  object  for  the  form Wednesday, 2 November 11 You want to figure out the flock from the URL, say “/flock/my-awesome-wubs”. DetailView does this, and like all class-based views is built up of composable little pieces, so you could bring in SingleObjectMixin, which provides get_object to do this. Then we could override get_form_class to set up the form dynamically. But this behaviour is generic, so…
  • 10. from  moreviews  import  * class  NewFlockWub(BoundCreateView):    model  =  Wub    bound_field  =  ‘flock’    queryset  =  WubFlock.objects.all() Wednesday, 2 November 11 If your BoundCreateView isn’t this easy, you’re doing it wrong. “Bound” because the Wub is bound to the WubFlock.
  • 11. class  DeleteWub(DeleteView):    model  =  Wub class  F(forms.ModelForm):    class  Meta:        model  =  Wub        exclude  =  (‘flock’,) class  UpdateWub(UpdateView):    model  =  Wub    form_class  =  F Wednesday, 2 November 11 We don’t have to worry about binding for deleting, and for updating we just ensure we don’t change the “flock” field.
  • 12. Wednesday, 2 November 11 But what about the WubFlock? We should be able to create it AND ITS WUBS in one go. In traditional function views you’d do this with forms and formsets within the same request. So we want to do the same thing in class-based views.
  • 13. class  ProcessMultipleFormsMixin:    """Modify  GET  and  POST  behaviour   to  construct  and  process  multiple   forms  in  one  go.  There's  always  a   primary  form,  which  is  a  ModelForm. By  the  time  secondary  forms  are   saved,  self.new_object  on  the  view   will  contain  the  primary  object,  ie   the  object  that  the  primary  form   operates  on.""" Wednesday, 2 November 11 This isn’t one of the five classes, this is just a mixin. It’s not named perfectly, because although it DOES process multiple forms at once, it assumes one is the main form. This allows us to save the PRINCIPAL object, and then leaves a reference for all the other forms to use.
  • 14. from  django.views.generic  import  * class  NewFlock(MultiCreateView):    model  =  WubFlock    forms_models  =  [        {            ‘model’:  Wub,            ‘extra’:  1,        }    ] Wednesday, 2 November 11 This syntax is a little opaque, but it didn’t seem worth creating yet more classes just as helpers when we have lists and dictionaries. The exclude of the project field in the ModelForm for making little Wubs is taken care of for you.
  • 15. from  django.views.generic  import  * class  UpdateFlock(MultiUpdateView):    model  =  WubFlock    forms_models  =  [        {            ‘model’:  Wub,            ‘extra’:  1,            ‘can_delete’:  True,        }    ] Wednesday, 2 November 11 extra and can_delete here are both passed through to modelformset_factory. You can also set form inside the dictionary so you don’t just get a default ModelForm but can customise to your heart’s content.
  • 16. from  django.views.generic  import  * class  UpdateFlock(MultiUpdateView):    …    def  get_forms(self):        class  WubInlineForm(ModelForm):            def  save(self):                #  perhaps  we  default  the                  #  name  based  on  the  flock?        self.forms_models[0][‘form’]              =  WubInlineForm        return  super(...)() Wednesday, 2 November 11 You can even dynamically adjust things if you so choose. In fact, you can avoid forms_models by implementing get_forms directly if you prefer.
  • 17. from  django.views.generic  import  * class  DeleteFlock(DeleteView):    model  =  WubFlock Wednesday, 2 November 11 And of course deleting a flock will delete its wubs via the evil of the ORM’s implementing CASCADE DELETE itself.
  • 18. Wednesday, 2 November 11 There’s also a variant which will allow you to create an object bound to another but which itself has children bound to it. It’s imaginatively called MultiBoundCreateView. That’s not one of the five, that’s a bonus one. However now we need to think about non-editing views again, because we’ve still got a problem.
  • 19. from  django.views.generic  import  * class  Wubs(ListView):    model  =  Wub class  Flock(DetailView):    model  =  WubFlock Wednesday, 2 November 11 This is fine until you have a flock with three thousand wubs in. And wubs are very gregarious.
  • 20. from  django.views.generic  import  * class  Wubs(ListView):    model  =  Wub    paginate_by  =  10 class  Flock(DetailView):    model  =  WubFlock Wednesday, 2 November 11 ListView has pagination built in. Wouldn’t it be nice if we could do that for the CHILDREN bound to the object in a DetailView?
  • 21. from  django.views.generic  import  * from  moreviews  import  * class  Wubs(ListView):    model  =  Wub    paginate_by  =  10 class  Flock(DetailListView):    model  =  WubFlock    paginate_by  =  10 Wednesday, 2 November 11 This is the fourth view. Warning: this exists, deep within the Artfinder codebase, but isn’t re- usable yet.
  • 22. Wednesday, 2 November 11 We’re not finished yet.
  • 23. From:  Your  Boss  <phb@myco.co.com> To:  You  <peon@myco.co.com> Subject:  Permissions Yo  dawg.  I  was  over  at  Big  Client   Co  this  morning  and  noticed  that   they’re  able  to  edit  the  WubFlock   for  the  Sinister  Government   Agency.  This  contains  proprietary   Wub  technology,  and  geese,  so  THIS   SHOULD  NOT  BE  ALLOWED. Wednesday, 2 November 11 Maybe your site allows everyone to see and do everything. Most don’t. What you used to do with function views was to check the permission at the top of the view and return a 403. In class-based views you need to do that around get_object, which gives you direct access to the object.
  • 24. def  editable():    def  decorator(fn):        @wraps(fn,  assigned=available_attrs(fn))        def  _wrapped_fn(self,  *args,  **kwargs):            obj  =  fn(self,  *args,  **kwargs)            if  obj.editable(self.request.user):                return  obj            else:                raise  HttpForbidden()        return  _wrapped_fn    return  decorator class  _UpdateFlock(UpdateFlock):    get_object  =          editable(UpdateFlock.get_object) Wednesday, 2 November 11 Oh god oh god I want to die. Ignore that decorators make most people’s heads hurt, just LOOK AT THAT CODE AT THE BOTTOM.
  • 25. class  _UpdateFlock(UpdateFlock):    get_object  =          editable(            UpdateFlock.get_object        ) Wednesday, 2 November 11 There is no way this is going to look nice, no matter how many lines we wrap it onto. So this is the fifth class…that I’m really hoping someone has written. I want to write something like the following.
  • 26. class  _UpdateFlock(UpdateFlock):    def  allowed(self):        return  self.object.editable(            self.request.user        ) Wednesday, 2 November 11 Which is basically the same but not ugly. I guess what we actually want here is a permissions- activating mixin.
  • 27. class  _UpdateFlock(    UpdateFlock,    SingleObjectPermissionsMixin):    def  allowed(self):        return  self.object.editable(            self.request.user        ) Wednesday, 2 November 11
  • 28. class  SingleObjectPermissionsMixin(    object):    def  get_object(self):        obj  =  super(            SingleObjectPermissionsMixin,            self).get_object()        if  not  self.allowed(obj):            raise  HttpForbidden()        return  obj    def  allowed(self):        raise  NotImplementedError() Wednesday, 2 November 11 So this would be the fifth class. I haven’t written this, but I assume someone has. I suspect as I have it here, there are lots of problems, not least that HttpForbidden doesn’t exist in Django itself and so you’re dependent on something else to not only provide it but catch it in middleware and do something sensible with it.
  • 29. Summary • BoundCreateView for making Wubs • MultiCreateView for making WubFlocks • MultiUpdateView to update WubFlocks • DetailListView for paginating child objects • SingleObjectPermissionsMixin is mythical Wednesday, 2 November 11 The first three are written, but Ben caught me by surprise by asking me to talk, so they aren’t packaged and they’re not directly tested. DetailListView needs extracting from well-used internal code. The permissions stuff is entirely speculative; maybe we don’t need it.
  • 30. Questions? • James Aylett • @jaylett • artfinder.com • http://bit.ly/djugl-art Wednesday, 2 November 11