django 1.1 tour
DESCRIPTION
Talk given at PyWeb-IL on 31st Aug 2009TRANSCRIPT
![Page 1: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/1.jpg)
Idan Gazit
PyWeb-IL, August 31st 2009
Django 1.1a tour of (some) new features
![Page 2: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/2.jpg)
![Page 3: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/3.jpg)
bit.ly/django11release notes are your friend
![Page 4: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/4.jpg)
omg i haz to rewrite mai code?
![Page 5: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/5.jpg)
No!
code you wrote for 1.0 should
“Just Work”
http://bit.ly/djangoapi
![Page 6: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/6.jpg)
With a few exceptions…
![Page 7: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/7.jpg)
With a few exceptions…
constraint names on 64-bit platforms
![Page 8: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/8.jpg)
With a few exceptions…
constraint names on 64-bit platforms
transactions in tests
![Page 9: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/9.jpg)
With a few exceptions…
constraint names on 64-bit platforms
transactions in tests
SetRemoteAddrFromForwardedFor middleware
![Page 10: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/10.jpg)
With a few exceptions…
constraint names on 64-bit platforms
transactions in tests
SetRemoteAddrFromForwardedFor middleware
saving of model formsets
![Page 11: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/11.jpg)
With a few exceptions…
constraint names on 64-bit platforms
transactions in tests
SetRemoteAddrFromForwardedFor middleware
saving of model formsets
names of uploaded files
![Page 12: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/12.jpg)
Also…
changed admin autodiscovery
if your urlconf contains:(r'^admin/(.*)', admin.site.root),
change it to be:(r'^admin/', include(admin.site.urls)),
![Page 13: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/13.jpg)
bit.ly/django11release notes are your friend
![Page 14: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/14.jpg)
1.1 new features
1290 tasty commits, 1200 bugs squashed
![Page 15: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/15.jpg)
1.1 new features
10k new lines of documentation
![Page 16: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/16.jpg)
That’s a lot of new code.(at least there’s a lot of new docs)
![Page 17: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/17.jpg)
New Features!not an exhaustive list.
![Page 18: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/18.jpg)
• Aggregates
• F() Expressions
• Model improvements
• Admin improvements
• Comment Moderation
![Page 19: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/19.jpg)
• Aggregates
• F() Expressions
• Model improvements
• Admin improvements
• Comment Moderation
OMGWTFBBQ!!
![Page 20: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/20.jpg)
Aggregates
![Page 21: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/21.jpg)
What are aggregates?
• aggregate()summary for entire query
• annotate()summary per row returned
![Page 22: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/22.jpg)
Aggregate Examples
What is the average age for all people?
>>> Person.objects.aggregate(Avg(‘age’)){‘age__avg’: 23.65}
IntFieldage
first_name CharField
CharFieldlast_name
Person
person FK
thing CharField
DecimalFieldprice
Purchases
![Page 23: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/23.jpg)
Aggregate Examples
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}
IntFieldage
first_name CharField
CharFieldlast_name
Person
person FK
thing CharField
DecimalFieldprice
Purchases
![Page 24: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/24.jpg)
Aggregate Examples
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}
IntFieldage
first_name CharField
CharFieldlast_name
Person
person FK
thing CharField
DecimalFieldprice
Purchases
No Chaining!
![Page 25: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/25.jpg)
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)
![Page 26: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/26.jpg)
Annotation
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__count4592810191
IntFieldage
first_name CharField
CharFieldlast_name
Person
person FK
thing CharField
DecimalFieldprice
Purchases
![Page 27: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/27.jpg)
Annotation
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_purchases4592810191
IntFieldage
first_name CharField
CharFieldlast_name
Person
person FK
thing CharField
DecimalFieldprice
Purchases
![Page 28: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/28.jpg)
Annotation
Which people have <=10 purchases?
q = Person.objects.annotate( num_purchases=Count(‘purchases’)).filter(num_purchases__lte=10)
IntFieldage
first_name CharField
CharFieldlast_name
Person
person FK
thing CharField
DecimalFieldprice
Purchases
![Page 29: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/29.jpg)
Annotation
Annotations work across JOINs:
What is the average purchase price for purchases made by each person?
Person.objects.annotate(min_price=Min(‘purchases__price’))
IntFieldage
first_name CharField
CharFieldlast_name
Person
person FK
thing CharField
DecimalFieldprice
Purchases
![Page 30: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/30.jpg)
Dizzy Yet?many possibilities
![Page 31: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/31.jpg)
Annotation
Order is important!
foo.filter().annotate() != foo.annotate().filter()
![Page 32: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/32.jpg)
F( ) expressions
![Page 33: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/33.jpg)
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()
![Page 34: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/34.jpg)
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 openTradingDay.objects.filter(closing__gte=F('opening') * 1.5)# All downhillTradingDay.objects.filter(opening=F('high'))# Works across JOINs# Stocks that have days with <10pt loss in valueStock.objects.filter(days__closing__gte=F('days__opening')-10.0)
![Page 35: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/35.jpg)
F( ) Expressions
Atomic DB Increment Operations!
class MyModel(): ... counter = models.IntegerField()
MyModel.objects.filter(id=someid).update(counter=F('counter')+1)
![Page 36: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/36.jpg)
Model Improvements
![Page 37: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/37.jpg)
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.
![Page 38: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/38.jpg)
Unmanaged Models
class MyModel(): ... # some fields which match your existing table's column types class Meta: managed = False
![Page 39: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/39.jpg)
Proxy Models
I already have a model, and want to change its python behavior without changing the underlying table structure.
![Page 40: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/40.jpg)
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
![Page 41: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/41.jpg)
admin improvements
![Page 42: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/42.jpg)
Admin Actions
![Page 43: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/43.jpg)
Custom Admin Actions
def add_cowbell(modeladmin, request, queryset): queryset.update(myfield='cowbell!')
![Page 44: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/44.jpg)
Custom Admin Actions
def add_cowbell(modeladmin, request, queryset): queryset.update(myfield='cowbell!')
add_cowbell.short_description = "More Cowbell!"
![Page 45: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/45.jpg)
Custom Admin Actions
def add_cowbell(modeladmin, request, queryset): for obj in queryset: obj.myfield += 'cowbell!' obj.save()
add_cowbell.short_description = "More Cowbell!"
![Page 46: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/46.jpg)
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]
![Page 47: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/47.jpg)
list_editable
![Page 48: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/48.jpg)
Generic Comment Moderation
![Page 49: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/49.jpg)
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()
![Page 50: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/50.jpg)
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)
![Page 51: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/51.jpg)
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)
![Page 52: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/52.jpg)
Random
![Page 53: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/53.jpg)
(r'^myapp/', include('myapp.urls', namespace='foo', app_name='bar'))
reverse(‘bar:mynamedurl’, args=[‘xyzzy’], current_app=‘foo’)
URL Namespaces
![Page 54: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/54.jpg)
{% for foo in bars %} <p>{{ foo.name }}</p>{% empty %} <p class="empty">No foos in bars!</p>{% endfor %}
For/Empty template tag
![Page 55: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/55.jpg)
• forms: hidden_fields() / visible_fields()
• auth using REMOTE_USER: IIS/mod_auth_sspi, mod_authnz_ldap, etc
• safeseq template filterlike safe but for lists
• django.shortcuts.redirect() view:def my_view(request): ... return redirect('some-view-name', foo='bar')
More Random!
![Page 56: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/56.jpg)
Many More!
![Page 58: Django 1.1 Tour](https://reader030.vdocument.in/reader030/viewer/2022020306/54b7b8064a7959bf688b4773/html5/thumbnails/58.jpg)
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