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()