What's coming in Django 1.2
===========================
Simon Willison - @simonw
DJUGL, 3rd December 2009
------------------------
http://code.djangoproject.com/wiki/Version1.2Roadmap
http://code.djangoproject.com/wiki/Version1.2Features
------------------------
CSRF: Cross site request forgery
Your admin panel:
<a href="/delete.php?id=5">Delete</a>
Evil.com...
<img src="http://admin.yoursite.com/delete.php?id=5" width=1 height=1>
Then social engineers one of your logged-in users to visit that page.
------------------------
Your admin panel, using POST:
<form action="/delete.php" method="post">
<input type="hidden" name="id" value="4">
<input type="submit" value="Delete">
</form>
On evil.com...
<form action="http://admin.yoursite.com/delete.php"
method="post">
<input type="hidden" name="id" value="4">
<input type="submit" value="Go">
</form>
<script>document.forms[0].submit()</script>
(Even better, they can hide the above in an invisible iframe)
------------------------
Solution:
<form action="/delete.php" method="post">
<input type="hidden" name="id" value="4">
<input type="hidden" name="csrf_token"
value="02384029384092">
<input type="submit" value="Go">
</form>
csrf_token must by unique to the currently logged in user.
------------------------
Improved CSRF protection
http://code.djangoproject.com/wiki/CsrfProtection
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
------------------------
Integrating logging
http://code.djangoproject.com/wiki/LoggingProposal
http://groups.google.com/group/django-developers/msg/7452fac3ae3b8175
http://code.djangoproject.com/ticket/12012
------------------------
Signing and signed cookies
http://code.djangoproject.com/wiki/Signing
http://github.com/simonw/django-signed
------------------------
Smart {% if %} tag
http://www.djangosnippets.org/snippets/1350/
http://groups.google.com/group/django-developers/browse_thread/thread/993d92334c27c717
------------------------
QuerySet.raw()
http://code.djangoproject.com/ticket/11863
>>> Entry.objects.all()
[<Entry: Entry one>,
<Entry: Entry two>,
<Entry: Entry three>,
<Entry: Entry four>]
>>> qs = Entry.objects.raw('select * from blog_entry')
>>> qs
select * from blog_entry
>>> type(qs)
<class 'django.db.models.query.RawQuerySet'>
>>> list(qs)
[<Entry: Entry one>,
<Entry: Entry two>,
<Entry: Entry three>,
<Entry: Entry four>]
>>> list(Entry.objects.raw('select * from blog_entry where id > %s', [2]))
[<Entry: Entry three>, <Entry: Entry four>]
------------------------
Multi-DB
http://code.djangoproject.com/ticket/1142
http://groups.google.com/group/django-developers/browse_thread/thread/7904c7da7cb0085f
http://github.com/alex/django/blob/multiple-db/docs/topics/db/multi-db.txt
http://lazypython.blogspot.com/2009/11/state-of-multidb-in-django.html
------------------------
# In settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'data.db',
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
},
'production': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'multidb_demo_production',
'USER': 'root',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}
------------------------
>>> from blog.models import Entry
>>> Entry.objects.all()
[<Entry: A blog entry in SQLite>]
>>> Entry.objects.using('default').all()
[<Entry: A blog entry in SQLite>]
>>> Entry.objects.using('production').all()
[<Entry: A blog entry in MySQL>, <Entry: Another blog entry in MySQL>]
>>> e = Entry.objects.using('production')[0]
>>> e._state.__dict__
{'db': 'production'}
>>> e.save(using = 'default') # WARNING: Over-writes SQLite item with same pk
>>> e
<Entry: A blog entry in MySQL>
------------------------
http://www.youtube.com/watch?v=7i5FlC1MpkE