by Stiod Desenvolvimento Web
Assine nosso RSS

Archive for the 'Python' Category

Django RequestContext

ricardo

O RequestContext do django serve para popular o template com variavés padrões, ou seja váriaveis comum aos templates. Quando você usar o RequestContext como parâmetro no render_to_response de sua view, ele usará os chamados context_processor setados na váriavel TEMPLATE_CONTEXT_PROCESSOR do settings.py do projeto(por padrão esta váriavel não esta no settings), funções que retornão um dicionário de dados.

 
TEMPLATE_CONTEXT_PROCESSORS = (
    "django.core.context_processors.auth",
    "django.core.context_processors.debug",
    "django.core.context_processors.i18n",
    "django.core.context_processors.media",
)
 

Para criar um contex_processor é só criar uma função da seguinte maneira, você pode criar um arquivo context_processor.py na pasta de sua app.

 
def teste_contex_processor(request):
    user = request.user
 
    return {
      'user':user,
      'ip_address': request.META['REMOTE_ADDR']
    }
 

e colocar o context_processor criado no settings

 
TEMPLATE_CONTEXT_PROCESSORS = (
    ...,
    "meuprojeto.app.context_processor.teste_context_processor",
)
 

Para usar o RequestContext no render_to_response, basta fazer o seguinte:

 
    ...
    return render_to_response(
        'templates/index.html',
        dicionario_de_dados,
        context_instance=RequestContext(request)
    )
 

*lembrando que você tem que passar request como parâmetro.

Reaproveitando a inteface do Admin do Django

Rafael Sierra

Finalmente o Django pra mim atingiu a perfeição, depois da minha surpresa com o {{ block.super }}, agora foi a vez de eu realizar um sonho meu: Aproveitar as interfaces maravilhosas de administração do Django.

Sempre é um verdadeiro pé no saco ter que ficar escrevendo código que você sabe que ta pronto, e mais sacal ainda quando o código ta a apenas "../../" de você, mas agora é um trabalho a menos que eu tenho :D (especialmente considerando a minha "super habilidade" com CSS).

Agora vamos ao que interessa, o conhecimento necessário pra fazer isso funcionar levou cerca de 4 horas pra ser adiquirido, foram 4 horas engolindo e reengolindo código do Django, mas no final resultou em uma view como a seguinte (ignorem os imports desnecessários):

 
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.utils.text import ugettext_lazy as _
from django.contrib.auth.decorators import login_required
from mysearch.profiles.models import Profile
from mysearch.profiles.admin import ProfileAdmin
from django.contrib import admin
from django.contrib.admin.views.main import ChangeList
 
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
 
@login_required
def index(request):
    admin_model = admin.site._registry[Profile]
    admin_model.admin_site.root_path = request.path
    cl = ChangeList(
        request,
        Profile,
        ProfileAdmin.list_display,
        ProfileAdmin.list_display_links,
        ProfileAdmin.list_filter,
        ProfileAdmin.date_hierarchy,
        ProfileAdmin.search_fields,
        ProfileAdmin.list_select_related,
        ProfileAdmin.list_per_page,
        admin_model)
    cl.query_set = cl.query_set.filter(user=request.user)
    cl.get_results(request)
 
    context = {
        'title': cl.title,
        'is_popup': cl.is_popup,
        'cl': cl,
        'has_add_permission': admin_model.has_add_permission(request),
        'root_path': admin_model.admin_site.root_path,
        'app_label': _('Profile'),
    }
 
    return render_to_response('admin/change_list.html',
        context, context_instance=RequestContext(request))
 

Vamos as explicações agora. Primeiramente, pra que isso funcione é preciso que seu model tenha sido registrado no Admin do Django, no meu caso o model utilizado foi esse chamado Profile.

Depois disso é criado um objeto do tipo `django.contrib.admin.views.main.ChangeList`, infelizmente todos os parametros devem ser passados, e essa foi a parte que mais me decepcionou, uma vez que todos os atributos poderiam ser resgatados com base no último argumento, ou simplesmente pedindo a classe que define o model, mas tudo bem, é um pequeno preço a se pagar pelo beneficio.

Após criar a variável `cl`, vem o ponto que meu deu maior dor de cabeça: Filtrar o que eu quero que apareca para o usuário. Nesse caso eu precisava que o usuário tivesse acesso apenas ao próprio conteudo, e pra isso adicionei o `.filter(user=request.user)`, porém, isso não basta, é preciso chamar a função `cl.get_results(request)` pra que ele possa atualizar a lista de resultados que vai ser usada

A váriavel `context`, neste caso, é usada pelo template `admin/change_list.html`, sinta-se a vontade para copiar o template da pasta do Django e colocar na sua pra editar.

Por fim, basta retornar o template que vai pegar o resultado e imprimir na tela pro seu usuário que será muito feliz :D
Observações
O template `admin/change_list.html` não imprime a tabela propriamente dia, ela utiliza uma tag (não documentada no site) chamada `result_list`, essa tag recebe um objeto do tipo `ChangeList` que é o nosso `cl`.

Você ainda vai precisa escrever uma view (ou aproveitar a do Admin) para fazer o handle quando o usuário clicar no objeto, mas essa é a parte fácil :P

Se tem algo que eu admiro muito no sistema de templates do Django, é a tag block, eu acho ela realmente f#!$ pra ca#@!&.

Só que recemente eu descobri algo nela que se eu estivesse em um ato sexual teria resultado em um fork(), que é a possibilidade de acessar o conteúdo antigo da tag antes dela ser sobrescrevida por você.

É extremamente simples, vamos pegar como exemplo o seguinte template `base.html`:

 
<html>
    <head><title>{% block title%}Meu site dahora{% endblock %}</html>
    <body>{% block content %}{% endblock %}
</html>
 

A parte legal fica por conta do bloco title. Até então, sempre que eu quizesse colocar "Meu site dahora | Home" no titulo, eu teria que fazer assim em um template filho:

 
{% extends "base.html" %}
{% block title %}Meu site dahora | Home{% endblock %}
 

O problema óbvio nesse caso, é que se um dia eu resolver trocar o titulo pra "O Jardineiro é Jesus", então eu vo ter que editar todo template que extende o template `base.html` pra arrumar isso.

Eis então que surge a solução

 
{% extends "base.html" %}
{% block title %}{{block.super}} | Home{% endblock %}
 

:D Simples e funcional. VIDA LONGA AO DJANGO!

Gerenciamento de usuários Trac com Django

Rafael Sierra

Uma das minhas maiores broncas com o Trac é na hora de gerenciar usuários.

Até poucos meses atrás eu costumava gerenciar os usuários com o famoso aplicativo htpasswd que utiliza um arquivo de texto simples pra gerenciar os usuários. O primeiro problema que eu tive com ele veio quando eu pensei:

Holly shit...se eu precisar definir permissões de acesso a diferentes Tracs eu to fucked

Foi então que eu resolvi procurar uma alternativa, e o primeiro (e mais obvio) lugar que eu procurei foi no Django, felizmente encontrei a documentação que ensina passo-a-passo como configurar o Apache para autenticar com o Django, é tão ridiculamente simples configurar que recomendo acessar o link por você mesmo e configurar.

Agora eu estava feliz, tinha 3 tracs pra administrar, felizmente, todos com as mesmas permissões de acesso e tudo sobre controle, gerenciamento de usuários centralizado e tudo mais. E eis que finalmente surge a oportunidade de por a prova o gerenciamento de permissões de acesso com o Trac do projeto Djapian (ainda não publicado), dessa forma fiz o seguinte:

  • Os 3 Tracs já existentes estão configurados para permitir apenas acesso de pessoas com o atributo is_staff habilidado
  • O novo Trac foi configurado para permitir acesso de qualquer pessoa que tenha a permissão djapian

Após configurar o Apache apropriadamente eu criei um usuário de teste pelo Admin do Django, feito isso, testei o usuário no Trac do Djapian e no Trac interno, resultado: Perfeito, conseguindo logar-se e negando autenticação respectivamente.

Agora estava tudo perfeito, até eu perceber um detalhe: O projeto Djapian é OpenSource, e eu gostaria que o wiki também fosse, porém, não gostaria de deixar habilitado a edição do mesmo por usuários anonimos, até por questões de rastreamento no caso de alguem apagar ou estragar uma página.

O problema: Como eu permito que usuários se cadastrem?
A solução: Construir um plugin para o Trac que faça a interface com o Django :D
Levei aproximadamente 1 dia útil de trabalho para desenvolver esse plugin que pode ser baixado aqui, o plugin é bem simples de se configurar e instalar, para isso siga os seguintes passos:

 
$ wget http://pub.stiod.com/TracDjangoAuth-0.1.tar.gz
$ tar -zxvf TracDjangoAuth-0.1.tar.gz
$ cd TracDjangoAuth-0.1
$ python setup.py bdist_egg
$ cp dist/TracDjangoAuth-0.1-*.egg /path/para/o/seu/trac/plugins/
 

Agora é preciso apenas editar o arquivo trac.ini e acrescentar no final dele as seguintes linhas:

 
[djangoauth]
# Adicione aqui sua permissao
django_permission_name = can_do_something
# Permissoes padroes para cada usuario que se cadastras
default_trac_permissions = WIKI_CREATE,WIKI_MODIFY,WIKI_VIEW
# Settings que deve ser usado
django_settings_module = some_project.settings
 

Apenas note que a opção django_permission_name requer apenas o atributo codename da permissão, diferentemente de seu equivalente no Apache, que precisa do nome da aplicação também como myapp.some_perm.

Feito isso apenas reinicie o Apache e divirta-se, o novo plugin irá criar um novo link chamado "Signup" para que seus usuários possam se cadastrar e se logar :)
Qualquer dúvida, bug, sugestão, correção ou patch, é só comentar ai em baixo ;)
Em tempo: Fiz esse plugin para o Trac 0.10.x, se você estiver disposto a migrar para o 0.11, saiba que a unica mudança é no sistema de templates, de ClearSilver para Genshi.

Criamos uma página para o projeto Djapian.

\o/

Djapian - Search API for Django with Xapian

Para quem não conhece, o Djapian, é um aplicativo que você pode incorporar à sua própria solução afim de permitir buscas nos textos, essencial em aplicativos como: Wiki, Blog, CMS e todo tipo de projeto que envolva colaboração de usuários em informação.

Acesse esse post para ver um artigo completo sobre o Djapian.

Mudar o nome da aplicação no admin do Django

Rafael Sierra

Atenção! Pode conter links inúteis

É incrivel, passei meus ultimos um ano e meio trabalhando em empresas de terceiros, porém, eu não sentia aquele prazer que só um verdadeiro programador sente ao programar.

Mãs! Tudo mudou quando decidimos (eu e mais 4 socios) que era hora de tocar a empresa seriamente, então eu sai da empresa onde trabalhava e segui viagem para minha própria empresa.

Bom, enrolei muito já, vamos ao que interessa.

Você já deve ter se revoltado com o Django, mais precisamente com o aplicativo Admin, quando você era obrigado a aceitar uma versão capitalizada (no sentido da primeira-letra-maiúscula, e não financeiro) do nome do seu aplicativo na tela inicial da administração.

Porém, agora sei que é possivel modificar esse nome que fica com fundo azul, tudo graças a uma introspecção no código do Django, algo que eu dificilmente faria trabalhando para terceiros (esse foi o motivo de eu ter escrito aquelas abobrinhas ali em cima :P), e ao que tudo indica, essa "funcionalidade", não está documentada (pelo menos não foi fácil encontrar informações sobre isso, tanto que devo um link aqui).

Pra resolver esse problema é simples, basta editar o model desejado e adicionar dentro da classe Meta um atributo chamado "app_label" (repare que ele não se encontra na documentação), e com isso o model será agrupado no nome que você der para ele, o interessante, é que você pode agrupar varios aplicativos dentro de uma só tabela, desde que todos os models tenham o mesmo nome no app_label.

Mas o mais bizarro mesmo, é que você pode modificar o app_label de outros aplicativos que não fazem parte do seu projeto, por exemplo, ao adicionar as seguintes linhas em algum model.py seu:

  1.  
  2. from django.contrib.auth.models import User
  3. User._meta.app_label = "AWAAAY"
  4.  

Você vai jogar o modelo User pra dentro da tabela AWAAAAY.

Só gostaria de deixar claro que usar essa "funcionalidade" (não sei se isso seria realmente uma funcionalidade, já que não está documentada) pode resultar em comportamentos adversos (do projeto, não seus), uma vez que eu não estudei completamente o código-fonte do Django pra saber até onde vão os efeitos desse atributo.

So, have fun with moderation.

Em tempo: Estou com o Django-1.0
Nota de copyright: A imagem que utilizei aqui pertence ao site http://djangoproject.com

Django com WSGI

ricardo

Para quem usa o mod_python para servir suas aplicações em Django e esta insatisfeito ou teve algum problemas com o mesmo. Pois é, eu mesmo tive um baita problemão com o mod_python e precisava de solução urgente, que fosse rápida e fácil de configurar, uma ótima alternativa que eu encontrei foi o mod_wsgi (http://code.google.com/p/modwsgi/), logo de inicio verifiquei que num servidor de alto acesso de usuários a diferença de performance foi visivelmente absurda, hoje em dia só uso o mod_wsgi.Não vou abranger instalação do mod_wsgi mas somente a configuração do Apache e do arquivo wsgi

No seu arquivo de configurção do apache

  1.  
  2. WSGIDaemonProcess user processes=2 maximum-requests=500 threads=1
  3. WSGIProcessGroup usergroup
  4. WSGIScriptAlias / /path/para/aplicacao # sabendo que é a pasta onde fica a aplicação e não ela
  5. Alias /public /path/para/aplicacao/app/public/
  6.  

crie um arquivo na pasta da sua aplicação com o nome app.wsgi

  1.  
  2. import os, sys
  3. sys.path.append('/path/para/aplicacao/')
  4. os.environ['DJANGO_SETTINGS_MODULE'] = 'app.settings'
  5. import django.core.handlers.wsgi
  6. application = django.core.handlers.wsgi.WSGIHandler()
  7.  

Maiores Informações: http://code.google.com/p/modwsgi/ e
http://code.google.com/p/modwsgi/wiki/InstallationInstructions

Referência:
http://ericholscher.com/blog/2008/jul/8/setting-django-and-mod_wsgi/

Hoje deparei com um pequeno problema no módulo EmailMessage do Django, eu precisava mandar um email oculto em uma certa funcionalidade, apesar do EmailMessage dar suporte a cópia oculta(BCC), ele definitvamente mostra para os outros destinatários do email quem foi enviado o email oculto(¬¬), dando uma buscadinha no Google encontrei essa snippet, FixedEmailMessage(http://www.djangosnippets.org/snippets/630/), que além de resolver este problema, também tem suporte a CC.

Vai la um exemplo:


FixedEmailMessage('titulo', 'corpo', from_email='ex@exemplo.com', to=['para@exemplo.com'], bcc=['oculto@email.com'], cc=['copiado@exemplo.com']).send()

Referência: http://www.djangosnippets.org/snippets/630/

GoTo: Agilizando acessos a comandos comuns

Rafael Sierra

Quantas vezes você já teve que abrir 5 terminais e em cada um digitar algo como:
ssh usuario@servidor -p porta

Ai depois tem que voltar em cada um pra digitar a senha e só então entrar no servidor.
Afim de agilizar um pouco esse processo, criei esse script que permite que você execute os comandos mais comuns com um simples:
goto 0

Para instalar o programa basta baixar o script aqui, colocar em algum lugar do seu path e adicionar permissão de execução:

$ wget http://blog.stiod.com.br/wp-content/uploads/goto
$ sudo mv goto /usr/bin/
$ sudo chmod +x /usr/bin/goto

A manutenção dos comandos é bastante simples, basta executar o goto sem passar nenhum argumento adicional e você vai cair na interface de gerencia dele, algo como:

Chose an option:

	add <command>
	del <id>
	edit <id <new-command>
	quit
	license
:

Para adicionar um comando na lista, basta digitar:
: add ssh user@servidor -p porta

Em seguida esse comando vai automaticamente aparecer na lista de comandos disponíveis:

Chose an option:
	0: ssh user@servidor -p porta

	add <command>
	del <id>
	edit <id> 

Lembrando que o comando pode ser qualquer coisa que esteja no seu $PATH e o "cd" (que faz parte do shell -seja bash, sh, ksh, etc-)

Para remover um comando da lista, basta digitar "del 0", ou o número do comando listado.
Caso queira modificar um comando, masta digitar "edit 0 comando novo".

Para executar um atalho, basta digitar no shell:

$ goto 0

E ele automaticamente vai executar o comando programado.

P.S.: Essa ideia não foi minha, ela foi kibada de um script que o Ulisses fez.

Raiz cúbica?

gabriel

Como que eu faço a raiz cúbica de um número em python?

Ué? Raiz cúbica é o mesmo que o numero elevado a 1/3.. a raiz quarta seria o numero elevado a 1/4... a raiz n seria o numero elevado a 1/n...

[python]
8 ** (1.0/3)
[/python]
ou ainda...
[python]
import math
math.pow(8, 1.0/3)
[/python]
Retorna a raiz cúbica de 8, que é 2.

*O (Um Ponto Zero) é para que o resultado retorne um float para elevar ao "número quebrado"..