associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

AgendaCGI

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"

# 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 = """<html>
<style type="text/css">
form {background: #80c0e0;
       border: 1px solid black;
       width: 400px;
       padding: 20px;
       margin: 1cm;
     }
tr.even {background: #c0f0e0;}
tr.odd {background: #d0d0f0}
table {border: 2px solid black; width: 600px}
input { margin-left: 25px;}
body {background: white; color: black}

</style>
<body>
<h1>Cadastro de telefones</h1>
%(body)s
</body>
</html>
"""

TEMPLATE_DATA = """<table>
    <tr>
        <th>Nome</th> <th>Telefone</th><th>Endereço</th>
    </tr>
    %(table_body)s
</table>
"""

TEMPLATE_ROW= """<tr class="%(class)s">
    <td>%(name)s</td>
    <td>%(phone)s</td>
    <td>%(address)s</td>
"""
TEMPLATE_FORM = """<form action="agenda.py" method="get">
Novo contato: <br />
    Nome: <input type="text" name="name" /> <br />
    Telefone: <input type="text" name="phone" /> <br />
    Endereço: <input  type="text" name="address" /> <br />
    <input type="submit" value="Criar/Atualizar" /> 
    <input type="reset" value="Limpar" />
</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 <tr> 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