A moving target —
1.3
request → data → document
http://example.com/news/recent/
{'today': '2014 February 8',
'top_stories': [
['World', [
{'headline': 'Django Weekend Starting',
'blurb': 'World leaders are happy that…',
'byline': 'Cardiff, Wales'},
{'headline': 'Olympics Celebrates Opening',
'blurb': 'With the lighting of the…',
'byline': 'Sochi, Russia'},
⋮
]}
{'today': '2014 February 8',
'top_stories': [['World', […]], …]}
World news on 2014 February 8
┌Django Weekend Starting───────────────────┐
│ Cardiff, Wales ─ World leaders are happy│
│ that students, programmers, and other… │
└──────────────────────────────────────────┘
┌Olympics Celebrates Opening───────────────┐
│ Sochi, Russia ─ With the lighting of the│
│ Olympic torch, the opening ceremony has…│
└──────────────────────────────────────────┘
{'today': '2014 February 8',
'top_stories': [['World', […]], …]}
<h2>World news on 2014 February 8</h2>
<article>
<h3>Django Weekend Starting</h3>
<span class="byline">Cardiff, Wales</span>
<p>World leaders are happy
that students, programmers, and other…</p>
</article>
<article>
<h3>Olympics Celebrates Opening</h3>
…
{'today': '2014 February 8',
'top_stories': [['World', […]], …]}
{% for topic, stories in top_stories %}
<h2>{{ topic }} news on {{ today }}</h2>
{% for story in stories %}
<article>
<h3>{{ story.headline }}</h3>
<span class="byline">{{ story.byline }}</span>
<p>{{ story.blurb }}</p>
</article>
{% endfor %}
{% endfor %}
def test_recent_news_page(self):
url = '/news/recent/'
html = self.client.get(url).content
self.assertIn(u'<h2>World ', html)
self.assertIn(u'<h2>World ', html)
request → (data) → document
Another approach
def recent_news_page(request):
context = {}
context['today'] = …
context['top_stories'] = …
return TemplateResponse(
request, 'recent_news.html', context)
def test_person_page(self):
url = '/person/brandon'
c = self.client.get(url).context
title, stories = c['top_stories'][0]
self.assertEqual(title, u'World')
View tests
Design tests
def front_page(request):
⋮
context['user'] = request.user
⋮
def recent_news_page(request):
⋮
context['user'] = request.user
⋮
def settings_page(request):
⋮
context['user'] = request.user
⋮
# Simple middleware example, for views
# returning TemplateResponses
class DesignMiddleware(object):
def process_template_response(
request, response):
context = response.context_data
context['user'] = request.user
1.3
1.6
connect() →
← Please authenticate
Identity, secret →
← Success
1. Query →
← Data
close() →
connect() →
← Please authenticate
Identity, secret →
← Success
2. Query →
← Data
close() →
settings.py
CONN_MAX_AGE = 600 # ten minutes
connect() →
← Please authenticate
Identity, secret →
← Success
1. Query →
← Data
2. Query →
← Data
3. Query →
← Data
⋮
1.6
1.6
Transactions are funny things
# Once upon a time
db> SELECT COUNT(*) FROM fast_changing_table;
1035 rows
# Then I waited several seconds
db> SELECT COUNT(*) FROM fast_changing_table;
1035 rows
# Then I waited several minutes
db> SELECT COUNT(*) FROM fast_changing_table;
1035 rows
db> SELECT COUNT(*) FROM fast_changing_table;
1102 rows
# Great! The table is updating now.
db> SELECT COUNT(*) FROM fast_changing_table;
1102 rows
# Hmm. But now it has stopped again
db> SELECT COUNT(*) FROM fast_changing_table;
1102 rows
# Drat.
What was happening?
db> SELECT COUNT(*) FROM fast_changing_table;
1102 rows
db> COMMIT;
OK
db> SELECT COUNT(*) FROM fast_changing_table;
1129 rows
with transaction.atomic():
@transaction.atomic()
def person_view(request):
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
⋮
1.6
1.7
@brandon_rhodes