Templates em Django

Django4FrontEnd

 

Autor: Carlos Batman

Templates in Django

Django4FrontEnd

 

Author: Carlos Batman

Templates em Django - Django4FrontEnd

Fat models
Thin views
STUPID TEMPLATES

fonte: Vokal

Páginas web...

Templates em Django - Django4FrontEnd

<div class="card">
  <header>Bla bla bla 1</header>
  <p>Texto 1</p>
  <footer>Footer 1</footer>
</div>
<div class="card">
  <header>Bla bla bla 2</header>
  <p>Texto 2</p>
  <footer>Footer 2</footer>
</div>
<div class="card">
  <header>Bla bla bla 3</header>
  <p>Texto 3</p>
  <footer>Footer 3</footer>
</div>
<!-- ... and MANY MORE! -->

Repetição...

Repetição...

Repetição...

Padrões!

<!-- Página de perfil de Joaquim -->
<div class="profile">
<p>Joaquim Raia</p>
<!-- Só deveria mostrar se tiver profissão -->
<p>Carpinteiro</p>
</div>

<!-- ... -->

<!-- Página de perfil de Joaquim -->
<div class="profile">
<p>Joaquim Raia</p>
<!-- Só deveria mostrar se tiver profissão -->
<p>Carpinteiro</p>
</div>

... com 'estrutura'

Templates em Django - Django4FrontEnd

<!-- What if we had ENTITIES? -->
{% for article in articles %}
<div class="card">
  <header>{{article.title}}</header>
  <p>{{article.tease}}</p>
  <footer>{{article.footnote}}</footer>
</div>
{% endfor %}
<!-- READABLE! -->

 

Padrões!

{% for profile in profiles %}
<div class="profile">
<p>{{profile.name}}</p>
{% if profile.job %}
<p>{{profile.job}}</p>
{% endif %}
</div>
{% endfor %}
<!-- READABLE -->

Estrutura...

Templates em Django - Django4FrontEnd

E se tivéssemos um molde?

<!DOCTYPE html>
<html lang="<!-- changes -->">
  <head>
    <title><!-- changes --></title>
    <link rel="stylesheet" type="text/css" href="stylesforeverything.css" />
    <script src="usethiseverywhere.js"></script>
  </head>
  <body>
    <!-- changes -->
  </body>
</html>

... como molde!

Templates em Django - Django4FrontEnd

E se tivéssemos um molde?

<!DOCTYPE html>
<html>
  <head>
    <title>{% block title %}{% endblock %}</title>
    <link rel="stylesheet" type="text/css" href="stylesforeverything.css" />
    <script src="usethiseverywhere.js"></script>
  </head>
  <body>
    {% block content %}{% endblock %}
  </body>
</html>

Templates em Django - Django4FrontEnd

fonte: https://docs.djangoproject.com/en/1.7/topics/templates/

Texto... com contexto!

 

  • {{variáveis}} replaced with values
  • {% tags %} lógica de template
  • templ. pode ser HTML, XML, CSV, etc.

'templates' Django?

Um template completo

Templates em Django - Django4FrontEnd

{% load staticfiles %}
<html>
    <head>
        <title>Django Girls blog</title>
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
        <link href='//fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
        <link rel="stylesheet" href="{% static 'css/blog.css' %}">
    </head>
    <body>
        <div class="page-header">
            <h1><a href="/">Django Girls Blog</a></h1>
        </div>

        <div class="content container">
            <div class="row">
                <div class="col-md-8">
                {% for post in posts %}
                    <div class="post">
                        <div class="date">
                            {{ post.published_date }}
                        </div>
                        <h1><a href="">{{ post.title }}</a></h1>
                        <p>{{ post.text|linebreaksbr }}</p>
                    </div>
                {% endfor %}
                </div>
            </div>
        </div>
    </body>
</html>

fonte: https://tutorial.djangogirls.org/en/template_extending/

Um template completo

Templates em Django - Django4FrontEnd

Templating Engines?

  • Contexto (variáveis...)
  • Gestão de partes de uma página
    • Cabeçalho principal
    • Rodapé principal
    • Barra de navegação
    • Meta informação...

Templates em Django - Django4FrontEnd

Caminhos 'reutilizáveis'

  • blog/templates/blog/list.html
  • polls/templates/polls/poll.html
  • polls/templates/polls/poll_list.html

Templates em Django - Django4FrontEnd

  • numa view ou inclusion tag, caminho é definido a partir da pasta de template:
    • "blog/list.html"
    • "polls/poll.html"
    • "polls/poll_list.html"
  • mais fácil 'substituir' na aplicação principal sem perder perceção da aplicação a que o template realmente pertence!

Fonte: Django Girls

Templates em Django - Django4FrontEnd

the Django template system is not simply Python embedded into HTML.

 

This is by design: the template system is meant to express presentation, not program logic

fonte: https://docs.djangoproject.com/en/1.8/topics/templates/

Templates em Django - Django4FrontEnd

{{variaveis}}

<div class="card">
  <header>{{title}}</header>
  <p>{{excerpt}}</p>
  <footer>{{footnote}}</footer>
</div>

Templates em Django - Django4FrontEnd

{{ variaveis }}

Certo

Errado

{{variavel}}
{{ variavel }}
{{ variavel_interessante }}
{{ variavel-com-hifens }}
{{ variavel com espacos }}

'-' é operador em Python (e não só...)

Templates em Django - Django4FrontEnd

{{variavel|filtrada}}

{% for story in story_list %}
<h2>
  <a href="{{ story.get_absolute_url }}">
    {{ story.headline|upper }}
  </a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
{% endfor %}
{% endblock %}
  • Podem ser encadeados
  • Retornam logo valores
  • ... podem ser usados no mesmo contexto que variáveis
    • ciclios for, por exemplo...

Templates em Django - Django4FrontEnd

Filtros Úteis

{{value|length}}

{{value|dictsort:"name"}}
{{value|dictsort:"author.age"}}

<!-- True = 'sim' -->
<!-- False = 'nao' -->
<!-- None = 'talvez' -->
{{ value|yesno:"sim,nao,talvez" }} 

<!-- neste caso, None = 'nao' -->
{{ value|yesno:"sim,nao" }} 

<!-- link fica logo à volta de um <a></a> -->
{{'olhem para www.google.com'|urlize}} 

{{ "<p>Nao queria nenhuma <em>tag</em> no meu conteudo</p>"|striptags }}

Templates em Django - Django4FrontEnd

Filtros Úteis

{{value|default:'Nada'}} <!-- False or None -->
{{value|default_if_none:'Nada'}} <!-- None and ONLY if None -->

{{"Batman"|upper}} <!-- "BATMAN" -->
{{"Robin"|lower}} <!-- "robin" -->
{{"BATMAN and rOBIN"|title}} <!-- titlecase - "Batman And Robin" -->

<p>Você tem {{num_trab}} trabalhador{{num_trab|pluralize:"es"}}</p>
<p>Você também tem {{num_funis}} funi{{num_cherries|pluralize:"l,s"}}.</p>
<!-- pode ser usado dentro de blocktrans -->

{{"My son my planet or me"|truncatechars:9}} <!-- "My son..." -->
{{"<p>All Saiyans</p>"|truncatechars_html:9}} <!-- "<p>All Sa...</p>" -->
{{"Prince of all Sayians"|truncatewords:3}} <!-- Prince of all... -->
<!-- DICA: tambem existe truncatewords_html -->

Templates em Django - Django4FrontEnd

Filtros Úteis

{{value|default:'Nada'}} <!-- False or None -->
{{value|default_if_none:'Nada'}} <!-- None and ONLY if None -->

{{"Batman"|upper}} <!-- "BATMAN" -->
{{"Robin"|lower}} <!-- "robin" -->
{{"BATMAN and rOBIN"|title}} <!-- titlecase - "Batman And Robin" -->

<p>Você tem {{num_trab}} trabalhador{{num_trab|pluralize:"es"}}</p>
<p>Você também tem {{num_funis}} funi{{num_cherries|pluralize:"l,s"}}.</p>
<!-- pode ser usado dentro de blocktrans -->

{{"My son my planet or me"|truncatechars:9}} <!-- "My son..." -->
{{"<p>All Saiyans</p>"|truncatechars_html:9}} <!-- "<p>All Sa...</p>" -->
{{"Prince of all Sayians"|truncatewords:3}} <!-- Prince of all... -->
<!-- DICA: tambem existe truncatewords_html -->

Templates em Django - Django4FrontEnd

Filtros Úteis - Add

<!-- assumamos numeric_value como 3 e string_value como 'Nada' -->
{{numeric_value|add:2}} <!-- 5 -->
{{value|add:' a apontar'}} <!-- 'Nada a apontar' (sem aspas) -->

Templates em Django - Django4FrontEnd

Filtros Úteis - Slice

<!-- some_list = [1, 3, 5, 9, 1, 23] -->
<!-- funciona como as listas em Python' -->

{{some_list|slice:':2'}} 
<!-- isto equivale a 
>>> some_list[:2]
-->
<!-- ate índice 2 -->
<!-- resultado: [1, 3] -->

{{some_list|slice:'1:6:2'}}
<!-- desde o índice 1 até o índice 6, de 2 em 2 -->
<!-- resultado: [3, 9, 23] -->

Templates em Django - Django4FrontEnd

{% tags %}

  • Podem alterar o contexto
  • Podem definir sub-contextos
  • Comportamentos diversos
  • Lógica

Templates em Django - Django4FrontEnd

{% tags %}

{% extends "base_generic.html" %}

{% block title %}{{ section.title }}{% endblock %}

{% block content %}
<h1>{{ section.title }}</h1>

{% for story in story_list %}
<h2>
  <a href="{{ story.get_absolute_url }}">
    {{ story.headline|upper }}
  </a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
{% endfor %}
{% endblock %}

Templates em Django - Django4FrontEnd

{% block %} {% extends%}

<!DOCTYPE html>
<html>
  <head>
    <title>{% block title %}{% endblock %}</title>
    <link rel="stylesheet" type="text/css" href="stylesforeverything.css" />
    <script src="usethiseverywhere.js"></script>
  </head>
  <body>
    {% block content %}{% endblock %}
  </body>
</html>

Templates em Django - Django4FrontEnd

No template expandido...

{% extends "base_generic.html" %}

{% block title %}{{ section.title }}{% endblock %}

{% block content %}
<h1>{{ section.title }}</h1>

{% for story in story_list %}
<h2>
  <a href="{{ story.get_absolute_url }}">
    {{ story.headline|upper }}
  </a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
{% endfor %}
{% endblock %}

Templates em Django - Django4FrontEnd

{% block %} {% extends%}

Block + Extends

A essência do que realmente torna esta "linguagem" numa Templating Engine

Templates em Django - Django4FrontEnd

Outro "expandido"...

<!-- extended.html -->
{% extends 'base.html' %}
{% block extra_head_content  %}
    {{ block.super }}
    {% comment %}
        sem este bloco, o <script>
        seria reescrito no template expandido
    {% endcomment %}
    <link rel="stylesheet" type="text/css" href="/static/css/account.css" />
{% endblock %}
<!-- base.html -->
{% load static %}
<html>
<head>
    <link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}" />
    {% block extra_head_content %}
    <script src="{% static 'default_script.js' %}"></script>
    {% endblock %}
</head>
<body>{% block content %}{% endblock %}
</html>

Templates em Django - Django4FrontEnd

No template "expandido"...

  • "Baseia-te neste esqueleto e adiciona SÓ o conteúdo"
  • Conteúdo fora de blocos é ignorado - para onde vai o conteúdo, afinal?
  • Blocos novos podem ser adicionados e "expandidos" por outro... mas não será demais?
  • Conteúdo por defeito será substituído, mas há alternativa

Templates em Django - Django4FrontEnd

{% include %}

<!-- Passa o contexto -->
{% include 'app/partials/component.html' %}
<!-- Nao passa o contexto -->
{% include 'app/partials/component.html' only %} 
<! -- conteudo mais variavel extra -->
{% include 'app/components/component.html' with extra='batman string' %} 
<!-- apenas variaveis definidas -->
{% include 'app/components/component.html' with extra=3 something=else only %} 
  • Não suportam blocos
  • Adicionam conteúdo a um template pai
  • Não há relação entre eles
  • Encarar como 'parciais' que 'copiam' o contexto

{% for %}

Templates em Django - Django4FrontEnd

{% for book in books %}  
  <li>{{ book }}</li>
{% empty %}
  <li>Sorry, there are no books.</li>
{% endfor %}
<!-- ex. 2 -->
{% for item in items %}
  {# se não for o primeiro ou segundo elemento... #}
  {# forloop.counter começa com 1... forloop.counter0 começa com 0 #}
  {% if forloop.counter > 2 %}
    <li>{{item}}</li>
  {# se for o último elemento... #}
  {% if forloop.last %}
      <li>Fim</li>  
  {% endif %}  
{% endfor %}
<!-- ex. 2.1 -->
{% for item in items %}
  {% if forloop.first %}
      <li>Início</li>  
  {% endif %}    
  {# se item for um dos dois últimos (dica por: Mickael Morgado) #}
  {% if forloop.revcounter < 2 %}
    <li>{{item}}</li>
  {# se for o último elemento... #}  
{% endfor %}

 

dica: Mickael Morgado

 

Templates em Django - Django4FrontEnd

Tags úteis

{% with total=business.employees|length companhia=business.company %}
    A companhia {{companhia}} tem: 
    {{ total }} trabalhador{{ total|pluralize:"es" }}
{% endwith %}
{# The 'with' tag CACHES a complex variable (makes a copy, not a reference) #}

{% verbatim %}
    {{if dying}}Still alive.{{/if}}
{% endverbatim %}
{% verbatim myblock %}
    Avoid template rendering via the {% verbatim %}{% endverbatim %} block.
{% endverbatim myblock %}

{% filter force_escape|lower %}
    This text will be HTML-escaped, and will appear in all lowercase.
{% endfilter %}

Templates em Django - Django4FrontEnd

fonte: Django Project

dica: João Guerreiro

 

Tags úteis

{% lorem 4 p random %}
<!-- 4 paragrafos de lorem ipsum, cada um dentro de um elemento 'p' -->
<!-- ultimo parametro eh opcional, mas se preenchido faz com que o possa
n comecar com 'lorem ipsum dolorem...' -->

<p>
{% lorem 23 w %}
<!-- 23 palavras latinas... wohoo! -->
</p>

Templates em Django - Django4FrontEnd

Casos Especiais

 

  • Traduções
  • Datas e tempos
  • Humanize
  • Formulários

Subdomínios de tags que podem requerer bibliotecas adicionais

Templates em Django - Django4FrontEnd

i18n

{% load i18n %}

<!-- python manage.py makemessages -a -->
<!-- python manage.py compilemessages -->

<p>{% trans "Uma string qualquer" %}</p>
<p>{% trans "comando" context "army ranking" %}</p> <!-- importante para diversos contextos -->
<p>{% trans variavel_em_contexto %}</p>

{% trans "Nao exibir ja" as titulo_traduzido %}
<title>{{ titulo_traduzido }}</title>

{% blocktrans %}
<p>Este bloco tem alguma {{variavel}} e <i>tags</i><br />
E requer cuidado especial</p>
{% endblocktrans %}

{% blocktrans with autor=livro.autor.nome|upper count quantidade=livro.vendidos   %}
O autor {{autor}} vendeu {{quantidade}} livro de {{livro.nome}}
{% plural %}
O autor {{autor}} vendeu {{quantidade}} livros de {{livro.nome}}
{% endblocktrans %}

Templates em Django - Django4FrontEnd

fonte (informação e exemplo): Django Project

i18n - Seletor de línguas

{% load i18n %}

<!-- obter lista de objetos com código 
e nome de línguas disponíveis para projeto -->
{% get_available_languages as languages %}

{% trans "View this category in:" %}
{% for lang_code, lang_name in languages %}
    <!-- dentro desta tag, tudo o que tenha traduções 
    irá ser adaptado à língua especificada -->
    {% language lang_code %}
    <a href="{% url 'category' slug=category.slug %}">
        {{ lang_name }}
    </a>
    {% endlanguage %}
{% endfor %}

Templates em Django - Django4FrontEnd

Datas e Tempos

<p>A data foi: {{ value|date:"D d M Y" }}</p>

<p>Faltam: {{ conference_date|timeuntil:from_date }}</p>
<p>Publicado há {{ blog_date|timesince:comment_date }}</p>

{{ value|time:"H:i" }}
{{ value|time }} <!-- vai buscar o TIME_FORMAT nas settings -->

Templates em Django - Django4FrontEnd

fonte: https://docs.djangoproject.com/en/1.7/topics/templates/

Humanize

{% load humanize %}

<!-- variam com a lingua/regiao -->

<p>{% apnumber 1 %}</p> <!-- one -->
<p>{% apnumber 10 %}</p> <!-- 10 -->

<p>{% intcomma 4500 %}</p> <!-- 4,500 -->

<p>{% naturalday somedate %}</p> <!-- now, 2 days ago... -->

<p>{% naturaltime somedate %}</p> <!-- now, a minute ago, 1 day and 3 hours ago... -->

<p>{% ordinal 1 %} <!-- 1st -->

Templates em Django - Django4FrontEnd

Formulários

<!-- todo o formulário com campos dentro de parágrafos -->
{{ form.as_p }}
<!-- todo o formulário com campos dentro de itens de lista -->
{{ form.as_ul }}

<!-- o campo, definido com o nome da propriedade do mesmo no formulário -->
{{ form.field }}


Mas, sendo Front-end developer, pode dar jeito renderizar o formulário e campos manualmente

Templates em Django - Django4FrontEnd

fontes: Django Docs Forms API (1.7), Stack Overflow

Formulários

<form method="POST">
    <!-- medida de segurança automática do django -->
    {{form.csrf}}
    
    <!-- campo input renderizado manualmente -->
    <input 
        id="{{form.field.id_for_label}}" 
        name="{{form.field.html_name}}" 
        {% if form.field.value %} 
        value="{form.field.value}" 
        {% endif %} 
    />
    <select id="{{form.field.id_for_label}}" name="{{form.field.html_name}}">
    {% for value,label in form.field.choices %}
      <option value="{{value}}"{% if form.field.value == value %} selected{% endif %}>
        {{ label }}
      </option>
    {% endfor %}
    </select>
</form>


  • form.csrf
  • form.field.id_for_label
  • form.field.html_name
  • form.field.value

Renderização manual

Templates em Django - Django4FrontEnd

fonte: https://docs.djangoproject.com/en/1.7/topics/templates/

Texto... com contexto!

 

  • Pasta templates de uma aplicação
  • ... app/templates/app... again?

Como usar?

Templates em Django - Django4FrontEnd

Afinal, onde vai MESMO buscar os templates?

 

 

# ate ao 1.6 (1.7?), era diferente
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'APP_DIRS': True, # inclui pasta templates de cada app instalada 
        'DIRS': '/path/to/my/templates'
    },
]

INSTALLED_APPS = ('myproject.polls', 'myproject.quizzes')

Pediram-me um template 'pages/about.html'.

Onde procuro?

  1. Em '/path/to/my/templates/about.html' ?
  2. Em '(...)/myproject/polls/templates/pages/about.html?
  3. Em '(...)/myproject/quizzes/templates/pages/about.html?

Ordem das aplicações importa!

Templates em Django - Django4FrontEnd

Personalização

 

 

# settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            # wow, ate caminhos ah mao temos
            # cuidado com os caminhos absolutos, amigos
            '/home/html/example',
            '/home/html/default',
        ],
        'OPTIONS': {
            'context_processors': ['...'],
            '...': '...'
        }
    },
    {
        # Jinja eh outro tipo de templating engine
        # temos um estagiario que gosta de Jinja E vai trabalhar numa pasta dif.
        'BACKEND': 'django.template.backends.jinja2.Jinja2',
        'DIRS': [
            '/home/html/somethingwithjinja'
        ],
    },
]

Templates em Django - Django4FrontEnd

É o que o erro diz

 

 

Dicas

  • Usar um base.html

  • Evitar lógica na camada de apresentação...

    • se possível evitar QUALQUER lógica

  • Queries? Lololololol...

  • {% url %} e {% static %} em vez de links absolutos

  • {% block %} mais rápido que {% include %}

Templates em Django - Django4FrontEnd

fonte: https://docs.djangoproject.com/en/1.10/topics/performance/#template-performance

Templates em Django - Django4FrontEnd

fonte: https://docs.djangoproject.com/en/1.7/topics/templates/

Texto... com contexto!

 

  • lógica de dados FORA dos templates

Respeito pelo arquiteto

Aquela 'base'

  • DRY - um esqueleto para todas as páginas?
    • document.head
    • cabeçalho principal
    • ...
  • Um ficheiro para tudo o que não é conteúdo
  • (quase) Tudo se irá 'extender' daqui
  • Padrão comum em projetos django

Templates em Django - Django4FrontEnd

Templates em Django - Django4FrontEnd

{% extends %} - 3 níveis

  • base.html
    • base_blog.html (exp. base.html)
      • blog/list.html (exp. base_blog.html)
      • blog/article.html (exp. base_blog.html)
    • base_mypages.html (expande base.html)
      • mypages/page.html (exp. base_mypages.html)
      • mypages/editor.html (exp. base_mypages.html)

As coisas no sítio certo

 

 

https://docs.djangoproject.com/en/1.10/topics/performance/

# QuerySet operation on the database
# fast, because that's what databases are good at
my_bicycles.count()

# counting Python objects
# slower, because it requires a database query anyway, and processing
# of the Python objects
len(my_bicycles)

# Django template filter
# slower still, because it will have to count them in Python anyway,
# and because of template language overheads
{{ my_bicycles|length }}

Templates em Django - Django4FrontEnd

fonte: https://docs.djangoproject.com/en/1.7/topics/templates/

Too much?

Não filtrar com condições em Templates?

Um template completo

Templates em Django - Django4FrontEnd

Cached Templates

Templates em Django - Django4FrontEnd

fonte: Cached Templates (official django documentation)

TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [os.path.join(BASE_DIR, 'templates')],
    'OPTIONS': {
        'loaders': [
            ('django.template.loaders.cached.Loader', [
                'django.template.loaders.filesystem.Loader',
                'django.template.loaders.app_directories.Loader',
            ]),
        ],
    },
}]
  • Uma vez detetados, instâncias Template ficam em cache
  • n é preciso encontrar de novo o ficheiro nas apps/caminhos
  • NÃO usar em desenvolvimento (ou cuidado)!

Templates em Django - Django4FrontEnd

 

 

  • guardar porções de template e/ou variáveis de contexto
  • Tempo pode ser definido em variável, nome não
  • requer um sistema definido em settings.py CACHE
  • Cuidado com DEV

Cache

{% load cache %}
{% cache 500 sidebar %} 
{% comment %} 
    parametro 1 - longevidade da cache (s)
    parametro 2 - nome opcional 
{% endcomment %}
<section>
    <p>{{request.user.username}}</p>
    ...
</section>
{% endcache %}

Templates em Django - Django4FrontEnd

 

 

  • guardar um fragmento diferente em função de um ou mais parâmetros

Cache

{% load cache %}
{% cache 500 sidebar request.user.username %}
    {% comment %}
    Vou ter uma versao CACHE diferente
    para CADA utilizador (request.user.username)
    {% endcomment %}
{% endcache %}

Templates in Django

By Miguel Costa

Templates in Django

Django templates are one of the key features of Python's (possibly) most popular web framework. In order to understand them, and set them apart from a typical html (or text) file, one must grasp two concepts: context and templatetags. Through this presentation, Carlos Batman provides a brief introduction (in Portuguese) to django templates with some practical examples.

  • 498