quarta-feira, 27 de março de 2013

Django - Processadores de contexto

Sempre que vamos processar um template por meio de uma view precisamos especificar diversas variáveis em todas as views. Por exemplo, é uma boa prática especificar as urls completas nos templates ao invés de só o caminho relativo. Para isso, precisaríamos recuperar o endereço base do seu site em todas as views manualmente. Ou então, dados processados relativos ao usuário atual. Teríamos que, na melhor das hipóteses, chamar um mesmo método em todas as views. Não seria muito mais fácil especificar isso uma vez só e o django carregar isso como valores "globais" em suas views? Pois bem, é exatamente isso que os processadores de contexto fazem.

Os processadores de contexto te permitem especificar diversas variáveis que são definidas automaticamente em todos os contextos automaticamente - sem precisar ficar as especificando em cada chamada ao método render_to_response(). Mesmo que os valores armazenados por essas variáveis necessitem ser processados para serem gerados, ou recuperados de um banco de dados.


Vamos começar com um exemplo sobre como criar uma variável "global" que fornece o endereço base de seu site. Explicamos como obter a essa url aqui. Depois de tudo que falamos, pode parecer que é algo complicado de ser feito, não é? Veja só. Criamos um arquivo na raiz do projeto chamado context_processors.py e colocamos o seguinte código dentro dele:
from django.utils.encoding import smart_str

def global_vars(request):
 current_base_url = request.build_absolute_uri()
    return {
        'url_base': smart_str(current_base_url),
        'url_absoluta': ( smart_str(current_base_url) + 
                          smart_str(request.get_full_path()) ),}
Falta um detalhe ainda, mas já deu pra notar que em nossos templates teremos as variáveis url_base, que vai armazenar o "domínio" (o endereço raiz) de seu site, e a variável url_absoluta, que vai armazenar a url da página atual. Qual o detalhe que falta? Especificar no settings.py que esse processador de contexto deve ser usado. Acrescente este código no seu settings.py:
...
from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS
TEMPLATE_CONTEXT_PROCESSORS += (
    'meu_projeto.context_processors.global_vars',
)
...
Lembre-se de substituir o "meu_projeto" pelo nome correto do seu projeto, ou tudo que vamos conseguir serão mensagens de erro.
Corrigido isso, já está pronto! Vá em um dos seus templates e teste imprimir o conteúdo de uma dessas variáveis:
<!DOCTYPE html>
<head>
 <title>Título da página - {{url_absoluta}}</title>
</head>
...
Claro que não precisamos parar por aí, podemos criar muitas outras variáveis. Só se lembre de criar variáveis que são realmente relevantes para o seu sistema. Pois, como são carregadas em todas as views, é um pouquinho mais de memória e processamento que serão utilizados. Não é muito, mas se não tomar cuidado pode acabar com a memória do seu servidor por carregar valores que são usados em poucas views. Lembre-se do nome da ferramenta: processador de contexto. Temos de nos ater ao que é relevante, útil e faz sentido no contexto de processar seus templates.

Quanto aos meus projetos, eu costumo deixar salvo este processador de contexto com várias variáveis, algumas redundantes, para escolher quais vou usar e quais não em cada projeto. Uma que ficou legal para usar em projetos em desenvolvimento local/online é a mostrar_ads, ela indica se o projeto está rodando na web ou na minha máquina verificando se a url começa com "http://localhost:" ou não. Útil para, por exemplo, ocultar propagandas ao rodar localmente, pois exibir propagandas localmente normalmente é entendido como atividade inválida e pode custar sua conta. Uma vez que com certeza não vai estar rodando online nem vai estar no domínio combinado: uma forma simples de tentar ganhar dinheiro fácil com propagandas. Mais simples ainda de ser detectada seja de propósito ou não.

Bem, temos algumas outras variáveis também, como as para guardar as url de login, logout e cadastro, os pedaços da url, etc. URLs que costumo usar no template principal e facilita bastante colocá-las aqui:
from meu_projeto import settings as proj_set
from django.utils.encoding import smart_str

def base_vars(request):
 current_base_url = request.build_absolute_uri()
    return {
        'MY_BASE_SITE_URL': proj_set.MY_BASE_SITE_URL,
        
  'LOGIN_URL': proj_set.LOGIN_URL,
        'SIGNIN_URL': proj_set.SIGNIN_URL,
        'LOGOUT_URL': proj_set.LOGOUT_URL,
  
  'url_base': current_base_url,
  'url_relativa': request.get_full_path(),
        'url_absoluta': ( smart_str(current_base_url) + 
                          smart_str(request.get_full_path()) ), 
        'mostrar_ads': current_base_url.find('http://localhost:') == -1 }

A variável MY_BASE_SITE_URL eu uso para armazenar a URL base do site quando ele já está pronto e não vai mais ser mudado de lugar.

Bem, por hoje é só pessoal!
Espero que isso os ajude tanto quanto me ajudou!




Nenhum comentário: