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 %}
Made with Slides.com