Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Django 1.1 Tour

3,270 views

Published on

Talk given at PyWeb-IL on 31st Aug 2009

Published in: Travel, Education
  • Looks like a good presentation from the slides!
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Django 1.1 Tour

  1. 1. Django 1.1 a tour of (some) new features Idan Gazit PyWeb-IL, August 31st 2009
  2. 2. bit.ly/django11 release notes are your friend
  3. 3. omg i haz to rewrite mai code?
  4. 4. No! code you wrote for 1.0 should “Just Work” http://bit.ly/djangoapi
  5. 5. With a few exceptions…
  6. 6. With a few exceptions… constraint names on 64-bit platforms
  7. 7. With a few exceptions… constraint names on 64-bit platforms transactions in tests
  8. 8. With a few exceptions… constraint names on 64-bit platforms transactions in tests SetRemoteAddrFromForwardedFor middleware
  9. 9. With a few exceptions… constraint names on 64-bit platforms transactions in tests SetRemoteAddrFromForwardedFor middleware saving of model formsets
  10. 10. With a few exceptions… constraint names on 64-bit platforms transactions in tests SetRemoteAddrFromForwardedFor middleware saving of model formsets names of uploaded files
  11. 11. Also… changed admin autodiscovery if your urlconf contains: (r'^admin/(.*)', admin.site.root), change it to be: (r'^admin/', include(admin.site.urls)),
  12. 12. bit.ly/django11 release notes are your friend
  13. 13. 1.1 new features 1290 tasty commits, 1200 bugs squashed
  14. 14. 1.1 new features 10k new lines of documentation
  15. 15. That’s a lot of new code. (at least there’s a lot of new docs)
  16. 16. New Features! not an exhaustive list.
  17. 17. • Aggregates • F() Expressions • Model improvements • Admin improvements • Comment Moderation
  18. 18. OM GW • Aggregates TF BB • F() Expressions Q! ! • Model improvements • Admin improvements • Comment Moderation
  19. 19. Aggregates
  20. 20. What are aggregates? • aggregate() summary for entire query • annotate() summary per row returned
  21. 21. Aggregate Examples Person Purchases first_name CharField thing CharField last_name CharField price DecimalField age IntField person FK What is the average age for all people? >>> Person.objects.aggregate(Avg(‘age’)) {‘age__avg’: 23.65}
  22. 22. Aggregate Examples Person Purchases first_name CharField thing CharField last_name CharField price DecimalField age IntField person FK What is the average age for all people? >>> Person.objects.aggregate(Avg(‘age’), Min(‘age’), Max(‘age’)) {‘age__avg’: 23.65, ‘age__min’: 14, ‘age__max’:87}
  23. 23. Aggregate Examples Person Purchases first_name CharField thing CharField last_name CharField price DecimalField age IntField person FK What is the average age for all people? >>> Person.objects.aggregate(Avg(‘age’), Min(‘age’), Max(‘age’)) {‘age__avg’: 23.65, ‘age__min’: 14, ‘age__max’:87} No Chaining!
  24. 24. Aggregation functions • Avg(field): average of field • Min(field): min of field • Max(field): max of field • Sum(field): sum of all values in the field • Count(field, distinct): num of related objects via field • StdDev(field, sample) • Variance(field, sample)
  25. 25. Annotation Person Purchases first_name CharField thing CharField last_name CharField price DecimalField age IntField person FK People ordered by number of purchases made q = Person.objects.annotate(Count(‘purchases’)).order_by( ‘-purchases__count’) >>> q[0] <Person: Material Girl> >>> q[0].purchases__count 4592810191
  26. 26. Annotation Person Purchases first_name CharField thing CharField last_name CharField price DecimalField age IntField person FK People ordered by number of purchases made q = Person.objects.annotate(num_purchases=Count(‘purchases’)) .order_by(‘-num_purchases’) >>> q[0] <Person: Material Girl> >>> q[0].num_purchases 4592810191
  27. 27. Annotation Person Purchases first_name CharField thing CharField last_name CharField price DecimalField age IntField person FK Which people have <=10 purchases? q = Person.objects.annotate( num_purchases=Count(‘purchases’)).filter(num_purchases__lte=10)
  28. 28. Annotation Person Purchases first_name CharField thing CharField last_name CharField price DecimalField age IntField person FK Annotations work across JOINs: What is the average purchase price for purchases made by each person? Person.objects.annotate(min_price=Min(‘purchases__price’))
  29. 29. Dizzy Yet? many possibilities
  30. 30. Annotation Order is important! foo.filter().annotate() != foo.annotate().filter()
  31. 31. F( ) expressions
  32. 32. F( ) Expressions class Stock(models.Model): symbol = models.CharField() class TradingDay(models.Model): stock = models.ForeignKey(Stock, related_name="days") opening = models.DecimalField() closing = models.DecimalField() high = models.DecimalField() low = models.DecimalField()
  33. 33. F( ) Expressions class Stock(models.Model): symbol = models.CharField() class TradingDay(models.Model): stock = models.ForeignKey(Stock, related_name="days") opening = models.DecimalField() closing = models.DecimalField() high = models.DecimalField() low = models.DecimalField() from django.db.models import F # Closed at least 50% up from open TradingDay.objects.filter(closing__gte=F('opening') * 1.5) # All downhill TradingDay.objects.filter(opening=F('high')) # Works across JOINs # Stocks that have days with <10pt loss in value Stock.objects.filter(days__closing__gte=F('days__opening')-10.0)
  34. 34. F( ) Expressions Atomic DB Increment Operations! class MyModel(): ... counter = models.IntegerField() MyModel.objects.filter(id=someid).update(counter=F('counter')+1)
  35. 35. Model Improvements
  36. 36. Unmanaged Models • Useful for tables or DB views which aren’t under Django’s control • Work like regular models • No table creation during syncdb, tests, etc.
  37. 37. Unmanaged Models class MyModel(): ... # some fields which match your existing table's column types class Meta: managed = False
  38. 38. Proxy Models I already have a model, and want to change its python behavior without changing the underlying table structure.
  39. 39. Proxy Models class MyProxy(MyModel): # no new fields! # but you can define new managers objects = SupaDupaProxyManager() proxy_specific_manager = PonyManager() class Meta: proxy = True ordering = ['not_the_original_ordering_field',] def my_proxy_method(self): # ... do something
  40. 40. admin improvements
  41. 41. Admin Actions
  42. 42. Custom Admin Actions def add_cowbell(modeladmin, request, queryset): queryset.update(myfield='cowbell!')
  43. 43. Custom Admin Actions def add_cowbell(modeladmin, request, queryset): queryset.update(myfield='cowbell!') add_cowbell.short_description = "More Cowbell!"
  44. 44. Custom Admin Actions def add_cowbell(modeladmin, request, queryset): for obj in queryset: obj.myfield += 'cowbell!' obj.save() add_cowbell.short_description = "More Cowbell!"
  45. 45. Custom Admin Actions def add_cowbell(modeladmin, request, queryset): for obj in queryset: obj.myfield += 'cowbell!' obj.save() add_cowbell.short_description = "More Cowbell!" class MusicAdmin(admin.ModelAdmin): list_display = ['artist', 'song'] ordering = ['artist',] actions = [add_cowbell]
  46. 46. list_editable
  47. 47. Generic Comment Moderation
  48. 48. django.contrib.comments. moderation class BlogPost(models.Model): title = models.CharField() body = models.TextField() posted = models.DateTimeField() enable_comments = models.BooleanField() is_public = models.BooleanField()
  49. 49. django.contrib.comments. moderation class BlogPost(models.Model): title = models.CharField() body = models.TextField() posted = models.DateTimeField() enable_comments = models.BooleanField() is_public = models.BooleanField() class BlogPostModerator(moderation.Moderator): email_notification = True enable_field = 'enable_comments' auto_close_field = 'posted' close_after = 14 moderation.moderator.register(BlogPost, BlogPostModerator)
  50. 50. django.contrib.comments. moderation class BlogPostModerator(moderation.Moderator): email_notification = True enable_field = 'enable_comments' auto_close_field = 'posted' close_after = 14 def allow(comment, content_object, request): # return False to delete comment def moderate(comment, content_object, request): # return True to moderate comment moderation.moderator.register(BlogPost, BlogPostModerator)
  51. 51. Random
  52. 52. URL Namespaces (r'^myapp/', include('myapp.urls', namespace='foo', app_name='bar')) reverse(‘bar:mynamedurl’, args=[‘xyzzy’], current_app=‘foo’)
  53. 53. For/Empty template tag {% for foo in bars %} <p>{{ foo.name }}</p> {% empty %} <p class="empty">No foos in bars!</p> {% endfor %}
  54. 54. More Random! • forms: hidden_fields() / visible_fields() • auth using REMOTE_USER: IIS/mod_auth_sspi, mod_authnz_ldap, etc • safeseq template filter like safe but for lists • django.shortcuts.redirect() view: def my_view(request): ... return redirect('some-view-name', foo='bar')
  55. 55. Many More!
  56. 56. Fin. @idangazit idan@pixane.com
  57. 57. Photo Credits • http://www.flickr.com/photos/josstyk/248920216/ • http://www.flickr.com/photos/mar00ned/3274556235/ • http://www.flickr.com/photos/ilumb/361819506/ • http://www.flickr.com/photos/womanofscorn/9163061/ • http://www.flickr.com/photos/ginnerobot/2549674296/ • http://www.flickr.com/photos/squaregraph/24869936 • http://www.flickr.com/photos/aresauburnphotos/3381681226 • http://www.flickr.com/photos/lwr/105783846/ • http://www.flickr.com/photos/jurvetson/447302275 • http://www.flickr.com/photos/leecullivan/240389468 • http://www.flickr.com/photos/pulpolux/3698819113

×