Class-based views with Django

13,580 views
13,453 views

Published on

Talk given at DJUGL in London on the 7th April 2009

Published in: Technology
0 Comments
19 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
13,580
On SlideShare
0
From Embeds
0
Number of Embeds
316
Actions
Shares
0
Downloads
218
Comments
0
Likes
19
Embeds 0
No embeds

No notes for slide

Class-based views with Django

  1. 1. Class-based views with Django Simon Willison DJUGL, 7th April 2009
  2. 2. Reusability A guiding principle of Django “Build applications, not projects” Generic views Thriving third party ecosystem
  3. 3. The Django contract A Django view is a function that takes a request object and returns a response object ORM, middleware, template language, forms, authentication system, admin, sites etc are all optional extras
  4. 4. Generic views Encapsulate common patterns in web development List of things / page about each things Things that are archived by date Things you can create/update/delete Let’s look at the code for object_detail
  5. 5. object_detail drawbacks You can’t swap the ORM for something else (without duck typing your own queryset) You have to use RequestContext You can’t modify something added to the context; you can only specify extra_context That’s despite a great deal of effort going in to making the behaviour customisable
  6. 6. newforms-admin De-coupled admin from the rest of Django Admin is just another application A new approach to customisation Powerful subclassing pattern
  7. 7. Finely grained permissions class Entry(models.Model): title = models.CharField(max_length=255) author = models.ForeignKey('auth.User') class EntryAdmin(admin.ModelAdmin): exclude = ('author',) def queryset(self, request): queryset = super(EntryAdmin, self).queryset(request) return queryset.filter(author = request.user) def save_model(self, request, obj, form, change): obj.author = request.user obj.save() def has_change_permission(self, request, ojb=None): if not obj: return True # access to change list return obj.author == request.user has_delete_permission = has_change_permission admin.site.register(Entry, EntryAdmin)
  8. 8. Finely grained permissions class Entry(models.Model): title = models.CharField(max_length=255) author = models.ForeignKey('auth.User') class EntryAdmin(admin.ModelAdmin): exclude = ('author',) def queryset(self, request): queryset = super(EntryAdmin, self).queryset(request) return queryset.filter(author = request.user) def save_model(self, request, obj, form, change): obj.author = request.user obj.save() def has_change_permission(self, request, ojb=None): if not obj: return True # access to change list return obj.author == request.user has_delete_permission = has_change_permission admin.site.register(Entry, EntryAdmin)
  9. 9. Finely grained permissions class Entry(models.Model): title = models.CharField(max_length=255) author = models.ForeignKey('auth.User') class EntryAdmin(admin.ModelAdmin): exclude = ('author',) def queryset(self, request): queryset = super(EntryAdmin, self).queryset(request) return queryset.filter(author = request.user) def save_model(self, request, obj, form, change): obj.author = request.user obj.save() def has_change_permission(self, request, ojb=None): if not obj: return True # access to change list return obj.author == request.user has_delete_permission = has_change_permission admin.site.register(Entry, EntryAdmin)
  10. 10. Finely grained permissions class Entry(models.Model): title = models.CharField(max_length=255) author = models.ForeignKey('auth.User') class EntryAdmin(admin.ModelAdmin): exclude = ('author',) def queryset(self, request): queryset = super(EntryAdmin, self).queryset(request) return queryset.filter(author = request.user) def save_model(self, request, obj, form, change): obj.author = request.user obj.save() def has_change_permission(self, request, ojb=None): if not obj: return True # access to change list return obj.author == request.user has_delete_permission = has_change_permission admin.site.register(Entry, EntryAdmin)
  11. 11. Finely grained permissions class Entry(models.Model): title = models.CharField(max_length=255) author = models.ForeignKey('auth.User') class EntryAdmin(admin.ModelAdmin): exclude = ('author',) def queryset(self, request): queryset = super(EntryAdmin, self).queryset(request) return queryset.filter(author = request.user) def save_model(self, request, obj, form, change): obj.author = request.user obj.save() def has_change_permission(self, request, ojb=None): if not obj: return True # access to change list return obj.author == request.user has_delete_permission = has_change_permission admin.site.register(Entry, EntryAdmin)
  12. 12. Finely grained permissions class Entry(models.Model): title = models.CharField(max_length=255) author = models.ForeignKey('auth.User') class EntryAdmin(admin.ModelAdmin): exclude = ('author',) def queryset(self, request): queryset = super(EntryAdmin, self).queryset(request) return queryset.filter(author = request.user) def save_model(self, request, obj, form, change): obj.author = request.user obj.save() def has_change_permission(self, request, ojb=None): if not obj: return True # access to change list return obj.author == request.user has_delete_permission = has_change_permission admin.site.register(Entry, EntryAdmin)
  13. 13. Objects can be views A Django view is a function that takes a request object and returns a response object A Django view is a callable that takes a request object and returns a response object
  14. 14. Objects can be views A Django view is a function that takes a request object and returns a response object A Django view is a callable that takes a request object and returns a response object Just define __call__() on the class
  15. 15. Example: restview.py http://www.djangosnippets.org/snippets/1071/
  16. 16. django_openid Next generation of my django-openid project Taken a lot longer than I expected Extensive use of class-based customisation
  17. 17. Ideas from django_openid Everything should go through a render() method Every template inherits from base_template Every decision should be a method Every form should come from a method Every model interaction should live in a method
  18. 18. TemplateResponse If you render_to_response, a subclass can’t override and reuse your method while modifying the context or template Solution: return TemplateResponse( request, 'article.html', context ) auth.py line 65
  19. 19. Class-based generic views Ticket #6735 Didn’t quite make 1.1; scheduled for 1.2
  20. 20. Subclassable decorators ratelimitcache is a decorator that implements rate limiting for a Django view It’s a class disguised as a function, using the __call__ method You can subclass it to customise its behaviour http://github.com/simonw/ratelimitcache/tree/master
  21. 21. Extending the contract Django view: take request / return response Django middleware: take request / return response Django application: take request / return response Django urlconf: take request / return response Django site: take request / return response
  22. 22. Thank you

×