= 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 = """ %(table_body)s
Nome TelefoneEndereço
""" TEMPLATE_ROW= """ %(name)s %(phone)s %(address)s """ TEMPLATE_FORM = """
Novo contato:
Nome:
Telefone:
Endereço:
""" #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