SlideShare a Scribd company logo
Advanced Templates
2013-07-23. Django Workshop.
About me
• TP (@uranusjr)	

• RTFD	

• Find me anywhere
Language Review
{% if is_logged_in %}!
Thanks for logging in!!
{% else %}!
Welcome to {{ website_name }}.!
{% endif %}
Template tags
{% if is_logged_in %}!
Thanks for logging in!!
{% else %}!
Welcome to {{ website_name }}.!
{% endif %}
Variables
{% if is_logged_in %}!
Thanks for logging in!!
{% else %}!
Welcome to {{ website_name }}.!
{% endif %}
Language Review
• Variables come from a context	

• Dictionary-like name-value mapping	

• A context is rendered by the template	

• Variable replacement	

• Template tag execution
Template
__init__(self, string)
render(self, context)
format	

string
context
rendered	

value
text	

file
dict object
from django.shortcuts import render_to_response!
!
def view_1(request):!
context_dict = {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR'],!
'message': 'I am view 1.'!
}!
return render_to_response('template1.html',!
context_dict)!
!
def view_2(request):!
context_dict = {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR'],!
'message': 'I am the second view.'!
}!
return render_to_response('template2.html',!
context_dict)
from django.shortcuts import render_to_response!
!
def view_1(request):!
context_dict = {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR'],!
'message': 'I am view 1.'!
}!
return render_to_response('template1.html',!
context_dict)!
!
def view_2(request):!
context_dict = {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR'],!
'message': 'I am the second view.'!
}!
return render_to_response('template2.html',!
context_dict)
from django.template import loader, Context!
!
def view_1(request):!
context_dict = {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR'],!
'message': 'I am view 1.'!
}!
t = loader.get_template('template1.html')!
context = Context(context_dict)!
return t.render(context)!
!
def view_2(request):!
context_dict = {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR'],!
'message': 'I am the second view.'!
}!
t = loader.get_template('template2.html')!
context = Context(context_dict)!
return t.render(context)
from django.template import loader, Context!
!
def view_1(request):!
context_dict = {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR'],!
'message': 'I am view 1.'!
}!
t = loader.get_template('template1.html')!
context = Context(context_dict)!
return t.render(context)!
!
def view_2(request):!
context_dict = {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR'],!
'message': 'I am the second view.'!
}!
t = loader.get_template('template2.html')!
context = Context(context_dict)!
return t.render(context)
from django.template import loader, Context!
!
def render_it(template, context_dict):!
context_dict.update({!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR']!
})!
return template.render(Context(context_dict))!
!
def view_1(request):!
t = loader.get_template('template1.html')!
context_dict = {'message': 'I am view 1.'}!
return render_it(t, context_dict)!
!
def view_2(request):!
t = loader.get_template('template2.html')!
context_dict = {!
'message': 'I am the second view.'!
}!
return render_it(t, context_dict)
from django.template import loader, Context!
!
def render_it(template, context_dict):!
context_dict.update({!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR']!
})!
return template.render(Context(context_dict))!
!
def view_1(request):!
t = loader.get_template('template1.html')!
context_dict = {'message': 'I am view 1.'}!
return render_it(t, context_dict)!
!
def view_2(request):!
t = loader.get_template('template2.html')!
context_dict = {!
'message': 'I am the second view.'!
}!
return render_it(t, context_dict)
from django.template import loader, RequestContext!
!
def custom_proc(request):!
return {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR']!
}!
!
def view_1(request):!
t = loader.get_template('template1.html')!
context = RequestContext(!
request, {'message': 'I am view 1.'},!
processors=[custom_proc]!
)!
return t.render(context)!
!
def view_2(request):!
t = loader.get_template('template2.html')!
context = RequestContext(!
request, {'message': 'I am the second view.'},!
processors=[custom_proc]!
)!
return t.render(context)
from django.template import loader, RequestContext!
!
def custom_proc(request):!
return {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR']!
}!
!
def view_1(request):!
t = loader.get_template('template1.html')!
context = RequestContext(!
request, {'message': 'I am view 1.'},!
processors=[custom_proc]!
)!
return t.render(context)!
!
def view_2(request):!
t = loader.get_template('template2.html')!
context = RequestContext(!
request, {'message': 'I am the second view.'},!
processors=[custom_proc]!
)!
return t.render(context)
from django.template import loader, RequestContext!
!
def custom_proc(request):!
return {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR']!
}!
!
def view_1(request):!
t = loader.get_template('template1.html')!
context = RequestContext(!
request, {'message': 'I am view 1.'},!
processors=[custom_proc]!
)!
return t.render(context)!
!
def view_2(request):!
t = loader.get_template('template2.html')!
context = RequestContext(!
request, {'message': 'I am the second view.'},!
processors=[custom_proc]!
)!
return t.render(context)
from django.shortcuts import render_to_response!
from django.template import RequestContext!
!
def custom_proc(request):!
return {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR']!
}!
!
def view_1(request):!
context = RequestContext(request, processors=[custom_proc])!
return render_to_response(!
'template1.html',!
{'message': 'I am view 1.'},!
context_instance=context!
)!
!
def view_2(request):!
context = RequestContext(request, processors=[custom_proc])!
return render_to_response(!
'template2.html',!
{'message': 'I am the second view.'},!
context_instance=context!
)
from django.shortcuts import render_to_response!
from django.template import RequestContext!
!
def custom_proc(request):!
return {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR']!
}!
!
def view_1(request):!
context = RequestContext(request, processors=[custom_proc])!
return render_to_response(!
'template1.html',!
{'message': 'I am view 1.'},!
context_instance=context!
)!
!
def view_2(request):!
context = RequestContext(request, processors=[custom_proc])!
return render_to_response(!
'template2.html',!
{'message': 'I am the second view.'},!
context_instance=context!
)
TEMPLATE_CONTEXT_PROCESSORS = (!
'django.contrib.auth.context_processors.auth',!
'django.core.context_processors.debug',!
'django.core.context_processors.i18n',!
'django.core.context_processors.media',!
'django.core.context_processors.static',!
'django.core.context_processors.tz',!
'django.contrib.messages.context_processors.messages',!
'myapp.views.custom_proc'!
)
settings.py
TEMPLATE_CONTEXT_PROCESSORS = (!
'django.contrib.auth.context_processors.auth',!
'django.core.context_processors.debug',!
'django.core.context_processors.i18n',!
'django.core.context_processors.media',!
'django.core.context_processors.static',!
'django.core.context_processors.tz',!
'django.contrib.messages.context_processors.messages',!
'myapp.views.custom_proc'!
)
settings.py
from django.shortcuts import render_to_response!
from django.template import RequestContext!
!
def custom_proc(request):!
return {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR']!
}!
!
def view_1(request):!
context = RequestContext(request)!
return render_to_response(!
'template1.html',!
{'message': 'I am view 1.'},!
context_instance=context!
)!
!
def view_2(request):!
context = RequestContext(request)!
return render_to_response(!
'template2.html',!
{'message': 'I am the second view.'},!
context_instance=context!
)
from django.shortcuts import render_to_response!
from django.template import RequestContext!
!
def custom_proc(request):!
return {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR']!
}!
!
def view_1(request):!
context = RequestContext(request)!
return render_to_response(!
'template1.html',!
{'message': 'I am view 1.'},!
context_instance=context!
)!
!
def view_2(request):!
context = RequestContext(request)!
return render_to_response(!
'template2.html',!
{'message': 'I am the second view.'},!
context_instance=context!
)
from django.shortcuts import render!
!
def custom_proc(request):!
return {!
'app': 'My app',!
'user': request.user,!
'ip_address': request.META['REMOTE_ADDR']!
}!
!
def view_1(request):!
return render(!
'template1.html',!
{'message': 'I am view 1.'}!
)!
!
def view_2(request):!
return render(!
'template2.html',!
{'message': 'I am the second view.'}!
)
Custom Processors
• Do one thing and do it well	

• Pick your variable names	

•Context keys are global	

• General import conventions apply
• Breaking down render_to_response	

• RequestContext and context processors	

• TEMPLATE_CONTEXT_PROCESSORS	

• django.shortcuts.render
Summary
HTML Escaping
• Variable values are escaped by default	

• {{ something|safe }}	

• {% autoescape off %}

Not escaped: {{ something }}

{% endautoescape %}!
• Literals in tags/filters are not escaped	

• {{ escaped|default:'1 < 2' }}
Template Loading
• django.template.loader	

• get_template(template_name)	

• select_template(template_names)!
• TemplateDoesNotExist!
• TEMPLATE_DIRS!
• TEMPLATE_LOADERS
PROJECT_ROOT = …!
!
!
TEMPLATE_DIRS = (!
os.path.join(PROJECT_ROOT, 'templates'),!
os.path.join(PROJECT_ROOT, 'other_templates')!
)!
!
TEMPLATE_LOADERS = (!
'django.template.loaders.filesystem.Loader',!
'django.template.loaders.app_directories.Loader',!
# 'django.template.loaders.eggs.Loader',!
)
1
2
3
• Loader order	

• Path order	

• Third-party apps will
be searched	

• App directory search
order is undefined
Questions?
The Django Book Chapter 9 - Django Workshop - Taipei.py
Template Tags
Before We Start...
• This is a HUGE topic	

• Read the documentation	

• Learn how others do it	

• Template processing is string manipulation	

• Slow, period	

• No fancy things unless necessary
Template Library
Template Library
Template Library
Name	

matters
Template Library
Don’t
forget this
Template Library
Naming is
important
Template Filter
• Takes one or zero arguments	

• Always returns something	

• Fails silently
{{ value|upper }}!
!
{{ value|add:arg }}
from django import template!
!
register = template.Library()!
!
!
def upper(value):!
"""Converts a string into all uppercase."""!
return value.upper()!
!
!
def add(value, arg):!
"""Adds the arg to the value."""!
return int(value) + int(arg)
from django import template!
!
register = template.Library()!
!
!
def upper(value):!
"""Converts a string into all uppercase."""!
return value.upper()!
!
!
def add(value, arg):!
"""Adds the arg to the value."""!
return int(value) + int(arg)
from django import template!
!
register = template.Library()!
!
!
def upper(value):!
"""Converts a string into all uppercase."""!
return value.upper()!
!
!
def add(value, arg):!
"""Adds the arg to the value."""!
return int(value) + int(arg)!
!
!
register.filter('upper', upper)!
register.filter('add', add)
from django import template!
!
register = template.Library()!
!
!
@register.filter(name='upper')!
def upper(value):!
"""Converts a string into all uppercase."""!
return value.upper()!
!
!
@register.filter(name='add')!
def add(value, arg):!
"""Adds the arg to the value."""!
return int(value) + int(arg)!
from django import template!
!
register = template.Library()!
!
!
@register.filter!
def upper(value):!
"""Converts a string into all uppercase."""!
return value.upper()!
!
!
@register.filter!
def add(value, arg):!
"""Adds the arg to the value."""!
return int(value) + int(arg)!
@register.filter!
def upper(value):!
"""Converts a string into all uppercase."""!
return value.upper()!
!
!
@register.filter!
def add(value, arg):!
"""Adds the arg to the value."""!
try:!
return int(value) + int(arg)!
except (ValueError, TypeError):!
try:!
return value + arg!
except Exception:!
return '' # Return something
@register.filter!
def upper(value):!
"""Converts a string into all uppercase."""!
return value.upper() # Let it fail!
!
!
@register.filter!
def add(value, arg):!
"""Adds the arg to the value."""!
try:!
return int(value) + int(arg)!
except (ValueError, TypeError):!
try:!
return value + arg!
except Exception:!
return ''
{{ value|upper }}!
!
{{ value|add:arg }}
{% load myapp_tags %}!
!
{{ value|upper }}!
!
{{ value|add:arg }}
{{ value|date:arg }}
from django.conf import settings!
from django.utils import formats!
!
@register.filter!
def date(value, arg=None):!
"""Formats a date according to the given format."""!
if value in (None, ''):!
return ''!
if arg is None:!
arg = settings.DATE_FORMAT!
try:!
return formats.date_format(value, arg)!
except AttributeError:!
try:!
return format(value, arg)!
except AttributeError:!
return ''
from django.conf import settings!
from django.utils import formats!
!
@register.filter!
def date(value, arg=None):!
"""Formats a date according to the given format."""!
if value in (None, ''):!
return ''!
if arg is None:!
arg = settings.DATE_FORMAT!
try:!
return formats.date_format(value, arg)!
except AttributeError:!
try:!
return format(value, arg)!
except AttributeError:!
return ''
from django.conf import settings!
from django.utils import formats!
!
@register.filter!
def date(value, arg=None):!
"""Formats a date according to the given format."""!
if value in (None, ''):!
return ''!
if arg is None:!
arg = settings.DATE_FORMAT!
try:!
return formats.date_format(value, arg)!
except AttributeError:!
try:!
return format(value, arg)!
except AttributeError:!
return ''
from django.conf import settings!
from django.utils import formats!
!
@register.filter!
def date(value, arg=None):!
"""Formats a date according to the given format."""!
if value in (None, ''):!
return ''!
if arg is None:!
arg = settings.DATE_FORMAT!
try:!
return formats.date_format(value, arg)!
except AttributeError:!
try:!
return format(value, arg)!
except AttributeError:!
return ''
Return Something
•Not necessarily a string	

•Only need to be convertible to a string	

• None is converted to 'None', not ''	

•I always return strings
Template Tags
Compilation	

function
Template tag node
__init__(self, string)
render(self, context)
template
context
rendered	

value
{% now format_string %}
from django import template!
from django.template import TemplateSyntaxError!
!
register = template.Library()!
!
!
@register.tag!
def now(parser, token):!
bits = token.split_contents()!
if len(bits) != 2:!
raise TemplateSyntaxError(!
"'now' statement takes one argument"!
)!
format_string = bits[1][1:-1]!
return NowNode(format_string)!
from django import template!
from django.template import TemplateSyntaxError!
!
register = template.Library()!
!
!
@register.tag!
def now(parser, token):!
bits = token.split_contents()!
if len(bits) != 2:!
raise TemplateSyntaxError(!
"'now' statement takes one argument"!
)!
format_string = bits[1][1:-1]!
return NowNode(format_string)!
from django import template!
from django.template import TemplateSyntaxError!
!
register = template.Library()!
!
!
@register.tag!
def now(parser, token):!
bits = token.split_contents()!
if len(bits) != 2:!
raise TemplateSyntaxError(!
"'now' statement takes one argument"!
)!
format_string = bits[1][1:-1]!
return NowNode(format_string)!
from django import template!
from django.template import TemplateSyntaxError!
!
register = template.Library()!
!
!
@register.tag!
def now(parser, token):!
bits = token.split_contents()!
if len(bits) != 2:!
raise TemplateSyntaxError(!
"'now' statement takes one argument"!
)!
format_string = bits[1][1:-1]!
return NowNode(format_string)!
from django import template!
from django.template import TemplateSyntaxError!
!
register = template.Library()!
!
!
@register.tag!
def now(parser, token):!
bits = token.split_contents()!
if len(bits) != 2:!
raise TemplateSyntaxError(!
"'now' statement takes one argument"!
)!
format_string = bits[1][1:-1]!
return NowNode(format_string)!
from django import template!
from django.template import TemplateSyntaxError!
!
register = template.Library()!
!
!
@register.tag!
def now(parser, token):!
bits = token.split_contents()!
if len(bits) != 2:!
raise TemplateSyntaxError(!
"'now' statement takes one argument"!
)!
format_string = bits[1][1:-1]!
return NowNode(format_string)!
from datetime import datetime!
!
!
class NowNode(Node):!
def __init__(self, format_string):!
self.format_string = format_string!
!
def render(self, context):!
now = datetime.now()!
return now.strftime(self.format_string)
from datetime import datetime!
!
!
class NowNode(Node):!
def __init__(self, format_string):!
self.format_string = format_string!
!
def render(self, context):!
now = datetime.now()!
return now.strftime(self.format_string)
from datetime import datetime!
from django.conf import settings!
from django.template.defaultfilters import date!
from django.utils import timezone!
!
!
class NowNode(Node):!
def __init__(self, format_string):!
self.format_string = format_string!
!
def render(self, context):!
if settings.USE_TZ:!
tzinfo = timezone.get_current_timezone()!
else:!
tzinfo = None!
return date(!
datetime.now(tz=tzinfo),!
self.format_string!
)
from datetime import datetime!
from django.conf import settings!
from django.template.defaultfilters import date!
from django.utils import timezone!
!
!
class NowNode(Node):!
def __init__(self, format_string):!
self.format_string = format_string!
!
def render(self, context):!
if settings.USE_TZ:!
tzinfo = timezone.get_current_timezone()!
else:!
tzinfo = None!
return date(!
datetime.now(tz=tzinfo),!
self.format_string!
)
{% inject_now format_string %}!
!
<p>The time is {{ now }}</p>
from django import template!
from django.template import TemplateSyntaxError!
!
register = template.Library()!
!
!
@register.tag!
def inject_now(parser, token):!
bits = token.split_contents()!
if len(bits) != 2:!
raise TemplateSyntaxError(!
"'inject_now' requires one argument"!
)!
format_string = bits[1][1:-1]!
return InjectNowNode(format_string)!
class InjectNowNode(Node):!
def __init__(self, format_string):!
self.format_string = format_string!
!
def render(self, context):!
if settings.USE_TZ:!
tzinfo = timezone.get_current_timezone()!
else:!
tzinfo = None!
context['now'] = date(!
datetime.now(tz=tzinfo),!
self.format_string!
)!
return ''
class InjectNowNode(Node):!
def __init__(self, format_string):!
self.format_string = format_string!
!
def render(self, context):!
if settings.USE_TZ:!
tzinfo = timezone.get_current_timezone()!
else:!
tzinfo = None!
context['now'] = date(!
datetime.now(tz=tzinfo),!
self.format_string!
)!
return ''
{% inject_now format_string as var_name %}!
!
<p>The time now is {{ var_name }}</p>
@register.tag!
def inject_now(parser, token):!
bits = token.split_contents()!
if len(bits) != 4:!
raise TemplateSyntaxError(!
"'inject_now' statement requires form "!
"{% inject_now format as var_name %}."!
)!
format_string = bits[1][1:-1]!
var_name = bits[3]!
return InjectNowNode(format_string, var_name)
@register.tag!
def inject_now(parser, token):!
error = TemplateSyntaxError(!
"'inject_now' statement requires form "!
"{% inject_now format as var_name %}."!
)!
try:!
tag_name, arg = token.contents.split(None, 1)!
except ValueError:!
raise error!
!
m = re.search(r'(.*?) as (w+)', arg)!
if m:!
fmt, var_name = m.groups()!
else:!
raise error!
if not (fmt[0] == fmt[-1] and fmt[0] in ('"', "'")):!
raise error!
!
return InjectNowNode(fmt[1:-1], var_name)
class InjectNowNode(Node):!
def __init__(self, format_string, var_name):!
self.format_string = format_string!
self.var_name = var_name!
!
def render(self, context):!
if settings.USE_TZ:!
tzinfo = timezone.get_current_timezone()!
else:!
tzinfo = None!
context[self.var_name] = date(!
datetime.now(tz=tzinfo),!
self.format_string!
)!
return ''
Start-end tags
• parser.parse(end_tags_tuple)!
• Returns a NodeList instance (iterable)	

• parser.delete_first_token()	

• Deletes next token (i.e. the end token)
def do_comment(parser, token):!
nodelist = parser.parse(('endcomment',))!
parser.delete_first_token()!
return CommentNode()!
!
!
class CommentNode(template.Node):!
def render(self, context):!
return ''
def do_comment(parser, token):!
nodelist = parser.parse(('endcomment',))!
parser.delete_first_token()!
return CommentNode()!
!
!
class CommentNode(template.Node):!
def render(self, context):!
return ''
def do_comment(parser, token):!
nodelist = parser.parse(('endcomment',))!
parser.delete_first_token()!
return CommentNode()!
!
!
class CommentNode(template.Node):!
def render(self, context):!
return ''
Shortcuts
• register.simple_tag	

• register.inclusion_tag(template)!
• takes_context=True!
• stringfilter
Custom Loaders
• implement load_template_source	

• Raise TemplateDoesNotExist when
appropriate	

• Add it to TEMPLATE_LOADERS in settings
Standalone Mode
• django.conf.settings.configure()	

• I’d just use another template engine	

• Jinja2 + Coffin	

• Read Appendix D or the docs if you really
know what you’re doing
Again...
• This is a HUGE topic	

• Read the documentation	

• Learn how others do it	

• Template processing is string manipulation	

• Slow, period	

• No fancy things unless necessary
Questions?

More Related Content

PPTX
jQuery, CSS3 and ColdFusion
PPTX
Lab#1 - Front End Development
PPTX
jQuery from the very beginning
PPTX
jQuery PPT
PDF
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
PPTX
jQuery
PDF
Building DSLs With Eclipse
PPTX
Introduction to jQuery
jQuery, CSS3 and ColdFusion
Lab#1 - Front End Development
jQuery from the very beginning
jQuery PPT
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
jQuery
Building DSLs With Eclipse
Introduction to jQuery

What's hot (19)

PPT
PDF
Headless Js Testing
KEY
Symfony2 Building on Alpha / Beta technology
PDF
Min-Maxing Software Costs - Laracon EU 2015
PDF
Workshop 8: Templating: Handlebars, DustJS
PDF
Class-based views with Django
PDF
Frontin like-a-backer
PPTX
Jquery Complete Presentation along with Javascript Basics
PDF
Advanced Django
PDF
jQuery Loves Developers - Oredev 2009
PPTX
Building High Performance Web Applications and Sites
PPTX
Powerful Generic Patterns With Django
PDF
The Django Book, Chapter 16: django.contrib
PDF
jQuery in 15 minutes
PDF
jQuery Essentials
PDF
Min-Maxing Software Costs
PPT
Object Oriented JavaScript
PPTX
Basics of Java Script (JS)
PPT
Headless Js Testing
Symfony2 Building on Alpha / Beta technology
Min-Maxing Software Costs - Laracon EU 2015
Workshop 8: Templating: Handlebars, DustJS
Class-based views with Django
Frontin like-a-backer
Jquery Complete Presentation along with Javascript Basics
Advanced Django
jQuery Loves Developers - Oredev 2009
Building High Performance Web Applications and Sites
Powerful Generic Patterns With Django
The Django Book, Chapter 16: django.contrib
jQuery in 15 minutes
jQuery Essentials
Min-Maxing Software Costs
Object Oriented JavaScript
Basics of Java Script (JS)
Ad

Viewers also liked (20)

PDF
Django - The Web framework for perfectionists with deadlines
PDF
Website optimization
PPT
Html5 History-API
PDF
2 × 3 = 6
ODP
Rabbitmq & Postgresql
PDF
User-centered open source
PDF
PythonBrasil[8] closing
PDF
Django e il Rap Elia Contini
PDF
라이트닝 토크 2015 파이콘
PPTX
2016 py con2016_lightingtalk_php to python
PDF
Django - The Web framework for perfectionists with deadlines
PDF
NoSql Day - Apertura
PDF
PyClab.__init__(self)
PDF
NoSql Day - Chiusura
ODP
Authentication & Authorization in ASPdotNet MVC
PDF
EuroDjangoCon 2009 - Ein Rückblick
PPT
Load testing
PDF
2007 - 应用系统脆弱性概论
PDF
Bottle - Python Web Microframework
PPT
Django-Queryset
Django - The Web framework for perfectionists with deadlines
Website optimization
Html5 History-API
2 × 3 = 6
Rabbitmq & Postgresql
User-centered open source
PythonBrasil[8] closing
Django e il Rap Elia Contini
라이트닝 토크 2015 파이콘
2016 py con2016_lightingtalk_php to python
Django - The Web framework for perfectionists with deadlines
NoSql Day - Apertura
PyClab.__init__(self)
NoSql Day - Chiusura
Authentication & Authorization in ASPdotNet MVC
EuroDjangoCon 2009 - Ein Rückblick
Load testing
2007 - 应用系统脆弱性概论
Bottle - Python Web Microframework
Django-Queryset
Ad

Similar to The Django Book Chapter 9 - Django Workshop - Taipei.py (20)

PPT
Django
KEY
Django quickstart
PDF
Rapid web application development using django - Part (1)
ODP
Introduction to Django
PPTX
Django Architecture Introduction
PPTX
The Django Web Application Framework 2
PPTX
The Django Web Application Framework 2
PPTX
The Django Web Application Framework 2
PPTX
The Django Web Application Framework 2
PDF
Flask intro - ROSEdu web workshops
PDF
The Django Book chapter 4 templates (supplement)
PDF
Django a whirlwind tour
PPTX
WRStmlDSQUmUrZpQ0tFJ4Q_a36bc57fe1a24dd8bc5ba549736e406f_C2-Week2.pptx
PDF
Django Girls Mbale [victor's sessions]
PPTX
Django crush course
PDF
GDG Addis - An Introduction to Django and App Engine
PPTX
Tango with django
KEY
Jumpstart Django
PDF
You've done the Django Tutorial, what next?
PDF
Web Development with Python and Django
Django
Django quickstart
Rapid web application development using django - Part (1)
Introduction to Django
Django Architecture Introduction
The Django Web Application Framework 2
The Django Web Application Framework 2
The Django Web Application Framework 2
The Django Web Application Framework 2
Flask intro - ROSEdu web workshops
The Django Book chapter 4 templates (supplement)
Django a whirlwind tour
WRStmlDSQUmUrZpQ0tFJ4Q_a36bc57fe1a24dd8bc5ba549736e406f_C2-Week2.pptx
Django Girls Mbale [victor's sessions]
Django crush course
GDG Addis - An Introduction to Django and App Engine
Tango with django
Jumpstart Django
You've done the Django Tutorial, what next?
Web Development with Python and Django

The Django Book Chapter 9 - Django Workshop - Taipei.py

  • 2. About me • TP (@uranusjr) • RTFD • Find me anywhere
  • 3. Language Review {% if is_logged_in %}! Thanks for logging in!! {% else %}! Welcome to {{ website_name }}.! {% endif %}
  • 4. Template tags {% if is_logged_in %}! Thanks for logging in!! {% else %}! Welcome to {{ website_name }}.! {% endif %}
  • 5. Variables {% if is_logged_in %}! Thanks for logging in!! {% else %}! Welcome to {{ website_name }}.! {% endif %}
  • 6. Language Review • Variables come from a context • Dictionary-like name-value mapping • A context is rendered by the template • Variable replacement • Template tag execution
  • 8. from django.shortcuts import render_to_response! ! def view_1(request):! context_dict = {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR'],! 'message': 'I am view 1.'! }! return render_to_response('template1.html',! context_dict)! ! def view_2(request):! context_dict = {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR'],! 'message': 'I am the second view.'! }! return render_to_response('template2.html',! context_dict)
  • 9. from django.shortcuts import render_to_response! ! def view_1(request):! context_dict = {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR'],! 'message': 'I am view 1.'! }! return render_to_response('template1.html',! context_dict)! ! def view_2(request):! context_dict = {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR'],! 'message': 'I am the second view.'! }! return render_to_response('template2.html',! context_dict)
  • 10. from django.template import loader, Context! ! def view_1(request):! context_dict = {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR'],! 'message': 'I am view 1.'! }! t = loader.get_template('template1.html')! context = Context(context_dict)! return t.render(context)! ! def view_2(request):! context_dict = {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR'],! 'message': 'I am the second view.'! }! t = loader.get_template('template2.html')! context = Context(context_dict)! return t.render(context)
  • 11. from django.template import loader, Context! ! def view_1(request):! context_dict = {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR'],! 'message': 'I am view 1.'! }! t = loader.get_template('template1.html')! context = Context(context_dict)! return t.render(context)! ! def view_2(request):! context_dict = {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR'],! 'message': 'I am the second view.'! }! t = loader.get_template('template2.html')! context = Context(context_dict)! return t.render(context)
  • 12. from django.template import loader, Context! ! def render_it(template, context_dict):! context_dict.update({! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR']! })! return template.render(Context(context_dict))! ! def view_1(request):! t = loader.get_template('template1.html')! context_dict = {'message': 'I am view 1.'}! return render_it(t, context_dict)! ! def view_2(request):! t = loader.get_template('template2.html')! context_dict = {! 'message': 'I am the second view.'! }! return render_it(t, context_dict)
  • 13. from django.template import loader, Context! ! def render_it(template, context_dict):! context_dict.update({! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR']! })! return template.render(Context(context_dict))! ! def view_1(request):! t = loader.get_template('template1.html')! context_dict = {'message': 'I am view 1.'}! return render_it(t, context_dict)! ! def view_2(request):! t = loader.get_template('template2.html')! context_dict = {! 'message': 'I am the second view.'! }! return render_it(t, context_dict)
  • 14. from django.template import loader, RequestContext! ! def custom_proc(request):! return {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR']! }! ! def view_1(request):! t = loader.get_template('template1.html')! context = RequestContext(! request, {'message': 'I am view 1.'},! processors=[custom_proc]! )! return t.render(context)! ! def view_2(request):! t = loader.get_template('template2.html')! context = RequestContext(! request, {'message': 'I am the second view.'},! processors=[custom_proc]! )! return t.render(context)
  • 15. from django.template import loader, RequestContext! ! def custom_proc(request):! return {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR']! }! ! def view_1(request):! t = loader.get_template('template1.html')! context = RequestContext(! request, {'message': 'I am view 1.'},! processors=[custom_proc]! )! return t.render(context)! ! def view_2(request):! t = loader.get_template('template2.html')! context = RequestContext(! request, {'message': 'I am the second view.'},! processors=[custom_proc]! )! return t.render(context)
  • 16. from django.template import loader, RequestContext! ! def custom_proc(request):! return {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR']! }! ! def view_1(request):! t = loader.get_template('template1.html')! context = RequestContext(! request, {'message': 'I am view 1.'},! processors=[custom_proc]! )! return t.render(context)! ! def view_2(request):! t = loader.get_template('template2.html')! context = RequestContext(! request, {'message': 'I am the second view.'},! processors=[custom_proc]! )! return t.render(context)
  • 17. from django.shortcuts import render_to_response! from django.template import RequestContext! ! def custom_proc(request):! return {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR']! }! ! def view_1(request):! context = RequestContext(request, processors=[custom_proc])! return render_to_response(! 'template1.html',! {'message': 'I am view 1.'},! context_instance=context! )! ! def view_2(request):! context = RequestContext(request, processors=[custom_proc])! return render_to_response(! 'template2.html',! {'message': 'I am the second view.'},! context_instance=context! )
  • 18. from django.shortcuts import render_to_response! from django.template import RequestContext! ! def custom_proc(request):! return {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR']! }! ! def view_1(request):! context = RequestContext(request, processors=[custom_proc])! return render_to_response(! 'template1.html',! {'message': 'I am view 1.'},! context_instance=context! )! ! def view_2(request):! context = RequestContext(request, processors=[custom_proc])! return render_to_response(! 'template2.html',! {'message': 'I am the second view.'},! context_instance=context! )
  • 21. from django.shortcuts import render_to_response! from django.template import RequestContext! ! def custom_proc(request):! return {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR']! }! ! def view_1(request):! context = RequestContext(request)! return render_to_response(! 'template1.html',! {'message': 'I am view 1.'},! context_instance=context! )! ! def view_2(request):! context = RequestContext(request)! return render_to_response(! 'template2.html',! {'message': 'I am the second view.'},! context_instance=context! )
  • 22. from django.shortcuts import render_to_response! from django.template import RequestContext! ! def custom_proc(request):! return {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR']! }! ! def view_1(request):! context = RequestContext(request)! return render_to_response(! 'template1.html',! {'message': 'I am view 1.'},! context_instance=context! )! ! def view_2(request):! context = RequestContext(request)! return render_to_response(! 'template2.html',! {'message': 'I am the second view.'},! context_instance=context! )
  • 23. from django.shortcuts import render! ! def custom_proc(request):! return {! 'app': 'My app',! 'user': request.user,! 'ip_address': request.META['REMOTE_ADDR']! }! ! def view_1(request):! return render(! 'template1.html',! {'message': 'I am view 1.'}! )! ! def view_2(request):! return render(! 'template2.html',! {'message': 'I am the second view.'}! )
  • 24. Custom Processors • Do one thing and do it well • Pick your variable names •Context keys are global • General import conventions apply
  • 25. • Breaking down render_to_response • RequestContext and context processors • TEMPLATE_CONTEXT_PROCESSORS • django.shortcuts.render Summary
  • 26. HTML Escaping • Variable values are escaped by default • {{ something|safe }} • {% autoescape off %}
 Not escaped: {{ something }}
 {% endautoescape %}! • Literals in tags/filters are not escaped • {{ escaped|default:'1 &lt; 2' }}
  • 27. Template Loading • django.template.loader • get_template(template_name) • select_template(template_names)! • TemplateDoesNotExist! • TEMPLATE_DIRS! • TEMPLATE_LOADERS
  • 28. PROJECT_ROOT = …! ! ! TEMPLATE_DIRS = (! os.path.join(PROJECT_ROOT, 'templates'),! os.path.join(PROJECT_ROOT, 'other_templates')! )! ! TEMPLATE_LOADERS = (! 'django.template.loaders.filesystem.Loader',! 'django.template.loaders.app_directories.Loader',! # 'django.template.loaders.eggs.Loader',! )
  • 29. 1 2 3 • Loader order • Path order • Third-party apps will be searched • App directory search order is undefined
  • 33. Before We Start... • This is a HUGE topic • Read the documentation • Learn how others do it • Template processing is string manipulation • Slow, period • No fancy things unless necessary
  • 39. Template Filter • Takes one or zero arguments • Always returns something • Fails silently
  • 40. {{ value|upper }}! ! {{ value|add:arg }}
  • 41. from django import template! ! register = template.Library()! ! ! def upper(value):! """Converts a string into all uppercase."""! return value.upper()! ! ! def add(value, arg):! """Adds the arg to the value."""! return int(value) + int(arg)
  • 42. from django import template! ! register = template.Library()! ! ! def upper(value):! """Converts a string into all uppercase."""! return value.upper()! ! ! def add(value, arg):! """Adds the arg to the value."""! return int(value) + int(arg)
  • 43. from django import template! ! register = template.Library()! ! ! def upper(value):! """Converts a string into all uppercase."""! return value.upper()! ! ! def add(value, arg):! """Adds the arg to the value."""! return int(value) + int(arg)! ! ! register.filter('upper', upper)! register.filter('add', add)
  • 44. from django import template! ! register = template.Library()! ! ! @register.filter(name='upper')! def upper(value):! """Converts a string into all uppercase."""! return value.upper()! ! ! @register.filter(name='add')! def add(value, arg):! """Adds the arg to the value."""! return int(value) + int(arg)!
  • 45. from django import template! ! register = template.Library()! ! ! @register.filter! def upper(value):! """Converts a string into all uppercase."""! return value.upper()! ! ! @register.filter! def add(value, arg):! """Adds the arg to the value."""! return int(value) + int(arg)!
  • 46. @register.filter! def upper(value):! """Converts a string into all uppercase."""! return value.upper()! ! ! @register.filter! def add(value, arg):! """Adds the arg to the value."""! try:! return int(value) + int(arg)! except (ValueError, TypeError):! try:! return value + arg! except Exception:! return '' # Return something
  • 47. @register.filter! def upper(value):! """Converts a string into all uppercase."""! return value.upper() # Let it fail! ! ! @register.filter! def add(value, arg):! """Adds the arg to the value."""! try:! return int(value) + int(arg)! except (ValueError, TypeError):! try:! return value + arg! except Exception:! return ''
  • 48. {{ value|upper }}! ! {{ value|add:arg }}
  • 49. {% load myapp_tags %}! ! {{ value|upper }}! ! {{ value|add:arg }}
  • 51. from django.conf import settings! from django.utils import formats! ! @register.filter! def date(value, arg=None):! """Formats a date according to the given format."""! if value in (None, ''):! return ''! if arg is None:! arg = settings.DATE_FORMAT! try:! return formats.date_format(value, arg)! except AttributeError:! try:! return format(value, arg)! except AttributeError:! return ''
  • 52. from django.conf import settings! from django.utils import formats! ! @register.filter! def date(value, arg=None):! """Formats a date according to the given format."""! if value in (None, ''):! return ''! if arg is None:! arg = settings.DATE_FORMAT! try:! return formats.date_format(value, arg)! except AttributeError:! try:! return format(value, arg)! except AttributeError:! return ''
  • 53. from django.conf import settings! from django.utils import formats! ! @register.filter! def date(value, arg=None):! """Formats a date according to the given format."""! if value in (None, ''):! return ''! if arg is None:! arg = settings.DATE_FORMAT! try:! return formats.date_format(value, arg)! except AttributeError:! try:! return format(value, arg)! except AttributeError:! return ''
  • 54. from django.conf import settings! from django.utils import formats! ! @register.filter! def date(value, arg=None):! """Formats a date according to the given format."""! if value in (None, ''):! return ''! if arg is None:! arg = settings.DATE_FORMAT! try:! return formats.date_format(value, arg)! except AttributeError:! try:! return format(value, arg)! except AttributeError:! return ''
  • 55. Return Something •Not necessarily a string •Only need to be convertible to a string • None is converted to 'None', not '' •I always return strings
  • 56. Template Tags Compilation function Template tag node __init__(self, string) render(self, context) template context rendered value
  • 58. from django import template! from django.template import TemplateSyntaxError! ! register = template.Library()! ! ! @register.tag! def now(parser, token):! bits = token.split_contents()! if len(bits) != 2:! raise TemplateSyntaxError(! "'now' statement takes one argument"! )! format_string = bits[1][1:-1]! return NowNode(format_string)!
  • 59. from django import template! from django.template import TemplateSyntaxError! ! register = template.Library()! ! ! @register.tag! def now(parser, token):! bits = token.split_contents()! if len(bits) != 2:! raise TemplateSyntaxError(! "'now' statement takes one argument"! )! format_string = bits[1][1:-1]! return NowNode(format_string)!
  • 60. from django import template! from django.template import TemplateSyntaxError! ! register = template.Library()! ! ! @register.tag! def now(parser, token):! bits = token.split_contents()! if len(bits) != 2:! raise TemplateSyntaxError(! "'now' statement takes one argument"! )! format_string = bits[1][1:-1]! return NowNode(format_string)!
  • 61. from django import template! from django.template import TemplateSyntaxError! ! register = template.Library()! ! ! @register.tag! def now(parser, token):! bits = token.split_contents()! if len(bits) != 2:! raise TemplateSyntaxError(! "'now' statement takes one argument"! )! format_string = bits[1][1:-1]! return NowNode(format_string)!
  • 62. from django import template! from django.template import TemplateSyntaxError! ! register = template.Library()! ! ! @register.tag! def now(parser, token):! bits = token.split_contents()! if len(bits) != 2:! raise TemplateSyntaxError(! "'now' statement takes one argument"! )! format_string = bits[1][1:-1]! return NowNode(format_string)!
  • 63. from django import template! from django.template import TemplateSyntaxError! ! register = template.Library()! ! ! @register.tag! def now(parser, token):! bits = token.split_contents()! if len(bits) != 2:! raise TemplateSyntaxError(! "'now' statement takes one argument"! )! format_string = bits[1][1:-1]! return NowNode(format_string)!
  • 64. from datetime import datetime! ! ! class NowNode(Node):! def __init__(self, format_string):! self.format_string = format_string! ! def render(self, context):! now = datetime.now()! return now.strftime(self.format_string)
  • 65. from datetime import datetime! ! ! class NowNode(Node):! def __init__(self, format_string):! self.format_string = format_string! ! def render(self, context):! now = datetime.now()! return now.strftime(self.format_string)
  • 66. from datetime import datetime! from django.conf import settings! from django.template.defaultfilters import date! from django.utils import timezone! ! ! class NowNode(Node):! def __init__(self, format_string):! self.format_string = format_string! ! def render(self, context):! if settings.USE_TZ:! tzinfo = timezone.get_current_timezone()! else:! tzinfo = None! return date(! datetime.now(tz=tzinfo),! self.format_string! )
  • 67. from datetime import datetime! from django.conf import settings! from django.template.defaultfilters import date! from django.utils import timezone! ! ! class NowNode(Node):! def __init__(self, format_string):! self.format_string = format_string! ! def render(self, context):! if settings.USE_TZ:! tzinfo = timezone.get_current_timezone()! else:! tzinfo = None! return date(! datetime.now(tz=tzinfo),! self.format_string! )
  • 68. {% inject_now format_string %}! ! <p>The time is {{ now }}</p>
  • 69. from django import template! from django.template import TemplateSyntaxError! ! register = template.Library()! ! ! @register.tag! def inject_now(parser, token):! bits = token.split_contents()! if len(bits) != 2:! raise TemplateSyntaxError(! "'inject_now' requires one argument"! )! format_string = bits[1][1:-1]! return InjectNowNode(format_string)!
  • 70. class InjectNowNode(Node):! def __init__(self, format_string):! self.format_string = format_string! ! def render(self, context):! if settings.USE_TZ:! tzinfo = timezone.get_current_timezone()! else:! tzinfo = None! context['now'] = date(! datetime.now(tz=tzinfo),! self.format_string! )! return ''
  • 71. class InjectNowNode(Node):! def __init__(self, format_string):! self.format_string = format_string! ! def render(self, context):! if settings.USE_TZ:! tzinfo = timezone.get_current_timezone()! else:! tzinfo = None! context['now'] = date(! datetime.now(tz=tzinfo),! self.format_string! )! return ''
  • 72. {% inject_now format_string as var_name %}! ! <p>The time now is {{ var_name }}</p>
  • 73. @register.tag! def inject_now(parser, token):! bits = token.split_contents()! if len(bits) != 4:! raise TemplateSyntaxError(! "'inject_now' statement requires form "! "{% inject_now format as var_name %}."! )! format_string = bits[1][1:-1]! var_name = bits[3]! return InjectNowNode(format_string, var_name)
  • 74. @register.tag! def inject_now(parser, token):! error = TemplateSyntaxError(! "'inject_now' statement requires form "! "{% inject_now format as var_name %}."! )! try:! tag_name, arg = token.contents.split(None, 1)! except ValueError:! raise error! ! m = re.search(r'(.*?) as (w+)', arg)! if m:! fmt, var_name = m.groups()! else:! raise error! if not (fmt[0] == fmt[-1] and fmt[0] in ('"', "'")):! raise error! ! return InjectNowNode(fmt[1:-1], var_name)
  • 75. class InjectNowNode(Node):! def __init__(self, format_string, var_name):! self.format_string = format_string! self.var_name = var_name! ! def render(self, context):! if settings.USE_TZ:! tzinfo = timezone.get_current_timezone()! else:! tzinfo = None! context[self.var_name] = date(! datetime.now(tz=tzinfo),! self.format_string! )! return ''
  • 76. Start-end tags • parser.parse(end_tags_tuple)! • Returns a NodeList instance (iterable) • parser.delete_first_token() • Deletes next token (i.e. the end token)
  • 77. def do_comment(parser, token):! nodelist = parser.parse(('endcomment',))! parser.delete_first_token()! return CommentNode()! ! ! class CommentNode(template.Node):! def render(self, context):! return ''
  • 78. def do_comment(parser, token):! nodelist = parser.parse(('endcomment',))! parser.delete_first_token()! return CommentNode()! ! ! class CommentNode(template.Node):! def render(self, context):! return ''
  • 79. def do_comment(parser, token):! nodelist = parser.parse(('endcomment',))! parser.delete_first_token()! return CommentNode()! ! ! class CommentNode(template.Node):! def render(self, context):! return ''
  • 81. Custom Loaders • implement load_template_source • Raise TemplateDoesNotExist when appropriate • Add it to TEMPLATE_LOADERS in settings
  • 82. Standalone Mode • django.conf.settings.configure() • I’d just use another template engine • Jinja2 + Coffin • Read Appendix D or the docs if you really know what you’re doing
  • 83. Again... • This is a HUGE topic • Read the documentation • Learn how others do it • Template processing is string manipulation • Slow, period • No fancy things unless necessary