= Aplicação CGI mínima - agenda de contatos =
Segue um exemplo de aplicação que gera um a págian html com formulário, processa
esse formulário e formata dados armazenados em html numa única página.
Digo de nota é que isso usa CGI enão quaquer framework python, nem nenhum módulo
externo ao core: é só colocr o arquivo stand-alone num diretório configurado
para servir CGI em qualquer máquina com um servidor http
(por exemlo, /var/www/cgi-bin em máquinas com Linux - não esquecer de marcar o
arquivo como executável), e apontar o navegador para "http://localhost/agenda.py"
"Funcionalidades extras são deixadas como um exercício para o leitor"
{{{
#! /usr/bin/env python
# coding: utf-8
# Autor: João S. O. Bueno
# Copyright: o mesmo
# Agenda.py - arquivo cgi para uma agenda minimalista
# em Python
# Licença de uso: Atribuir ao autor original, re-uso,
# obras derivadas,e uso comercial permitidos
"""
Notas do autor:
este programa é feito apra ser um exemplo.
Não tem nenhuma validação de entrada, e
está sujeito a quebrar de várias maneiras
"""
#importa os módulos
import sys
import cgi
import cgitb
from cPickle import load, dump
# Habilita a renderização de tracebacks no browser
# no caso de erro - facilita o desenvolvimento
cgitb.enable()
#Várias strings usadas como templates para o HTTP e o HTML:
# no corpo do programa, as partes identificadas com "%(chave)s
# são subsituidas pelos valores correspondentes de um
# dicionário fornecido como dado para o operador " % "
HEADER = """Content-Type: text/html;charset=utf-8\n\n"""
TEMPLATE_BODY = """
Cadastro de telefones
%(body)s
"""
TEMPLATE_DATA = """
Nome | Telefone | Endereço |
%(table_body)s
"""
TEMPLATE_ROW= """
%(name)s |
%(phone)s |
%(address)s |
"""
TEMPLATE_FORM = """
"""
#Path para o arquivo de dados
#FIXME: ajuste-o para um caminho não acessível pelo servidor http
DATAFILE = "contacts.pickle"
def main():
""" controle da aplicação -
chamado uma vez a cada page view
"""
form = get_cgi_data()
# desserializa lista de contatos gravada em arquivo
try:
contacts = load(open(DATAFILE, "rb"))
except IOError:
#lançado quando o arquivo não existe ainda - usar lista vazia:
contacts = []
if form["name"]:
# se o nome enviado já não existir
if not update_name(form, contacts):
# cria novo contato
contacts.append(form)
# ordena a lista de contatos, usando como
# chave o campo "name" de cada contato
contacts.sort(key=lambda c: c["name"])
#grava dados de contatos atualizados
dump(contacts, open(DATAFILE, "wb"), protocol=-1)
html_output(contacts)
def get_cgi_data():
""" obtem os dados do formulário,
criando entradas em branco quando não houver o dado
"""
form = cgi.FieldStorage()
form_data = {}
for attrib in ("name", "phone", "address"):
if attrib in form:
form_data[attrib] = form[attrib].value.strip()
else:
form_data[attrib] = ""
return form_data
def update_name(form, contacts):
"""
Verifica se nome já existes na lista de contatos
se sim, atualiza seus dados
"""
for contact in contacts:
if contact["name"] == form["name"]:
contact.update(form)
return True
return False
def html_output(contacts):
"""gera saida http + html final,
concatenando os templates, e criando
o corpo dos templates que tem que ser preenchidos
"""
sys.stdout.write(HEADER)
if contacts:
odd = True
html_contacts = []
for contact in contacts:
# insere dado alternado de classe html
# para cada contato
contact["class"] = "odd" if odd else "even"
html_contacts.append(TEMPLATE_ROW % contact)
odd = not odd
# reune todos os contatos, formatados individualmente
# como uma
em html no corpo da tabela html
html_data = TEMPLATE_DATA % {"table_body":
"\n".join(html_contacts)}
else:
html_data = ""
body = html_data + TEMPLATE_FORM
html = TEMPLATE_BODY % {"body": body}
sys.stdout.write(html)
if __name__ == "__main__":
#o modulo é o porgrama principal, e não está
# sendo importado por outro módulo
# (lembrando que para CGI's cada page view
# significa uma execução de todo o programa)
main()
}}}
CookBook