Documentação da aplicação de teste: pyramid!¶
O que é isto?¶
Este documento visa demonstrar como foi desenvolvida a aplicação aqui denominada PYRAMID. Na verdade, esta é apenas uma aplicação de teste, desenvolvida como treino para o aprendizado do framework Pyramid, utilizando a linguagem de programação PYTHON. Além disso, de maneira simplória, é feita a integração com o SQLAlchemy, que é um framework próprio para interação com base de dados.
Estrutura de arquivos e diretórios¶
__init__.py – Configuração inicial.
models.py – Camada de acesso á dados.
scripts – Onde se localizam os scripts de atualização ou manutenção da aplicação.
static– Onde ficam os arquivos estáticos.
templates – Arquivos de visualização.
tests.py – Testes automatizados.
views.py – Camada de negócio da aplicação.
Instalação¶
Tal configuração é para ser feito no terminal de uma máquina linux. A máquina em uso é Centos versão 7. Caso utilize outro tipo de sistema operacional, é necessário rever a síntaxe adotada.
- yum install sqlite-devel git
- virtualenv egito
- cd egito
- bin/activate ou ‘. bin/activate’
- pip install “pyramid==1.6”
- bin/pcreate -s alchemy tutorial
- rm -rf tutorial/*
- git clone https://github.com/wagnerwar/piramid.git tutorial
- cd tutorial/
- python setup.py develop
- cd ../
- bin/initialize_tutorial_db tutorial/development.ini
Modelo de dados¶
Arquivo models.py
1 2 3 4 5 6 7 8 | class Video(Base):
__tablename__ = 'video'
id = Column(Integer, primary_key=True)
name = Column(Text)
descricao = Column(Text)
preco = Column(Float)
Index('my_index', Video.name, unique=True, mysql_length=255)
|
Arquivo scripts/initializedb.py
1 2 3 4 5 6 7 8 9 10 11 12 13 | def main(argv=sys.argv):
if len(argv) < 2:
usage(argv)
config_uri = argv[1]
options = parse_vars(argv[2:])
setup_logging(config_uri)
settings = get_appsettings(config_uri, options=options)
engine = engine_from_config(settings, 'sqlalchemy.')
DBSession.configure(bind=engine)
Base.metadata.create_all(engine)
with transaction.manager:
model = Video(name='one', preco=1)
DBSession.add(model)
|
Se atente para as duas linhas acima, no qual é feita a inserção de um registro para fins de teste.
- Sincronização e criação das tabelas
- bin/initialize_tutorial_db tutorial/development.ini – Onde tutorial/development.ini é o arquivo de configuração
Como visto acima, a classe Video representa a tabela video, com os seguintes atributos: id,name,descricao e preco. O framework SqlAlchemy permite que, não manipulemos dados diretamente, mas, objetos, que representam estes dados. Por isso, não precisa conhecer a estrutura dos dados, apenas, saber usar a camada de abstração destes dados. Os mesmos dados podem estar no SQLite ou no POSTGRESQL; não importa, a forma de manipulá-los é a mesma. Foi criado um índice chamada my_index associado com a tabela video.
Cadastro¶
Arquivo __init__.py
1 2 3 4 5 | def main(global_config, **settings):
config.include(videos_include, route_prefix='/videos')
def videos_include(config):
config.add_route('cadastrar', '/cadastrar')
|
Conforme visto acima, estão configuradas todos os caminhos iniciados com ‘videos/’ dentro da função videos_include. Por exemplo, quando digitamos ‘videos/cadastrar’, será carregada a view cadastrar, cujo conteúdo segue abaixo, no arquivo views.py.
Arquivo views.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @view_config(route_name='cadastrar',renderer='templates/cad.pt')
def cadastrar(request):
save_url = request.route_url('cadastrar')
request.route_url('consulta')
if request.params:
print('PASSOU')
nome = request.params['nome']
descricao = request.params['descricao']
preco = request.params['preco']
novo_video = Video(name=nome,descricao=descricao,preco=preco)
try:
DBSession.add(novo_video)
return HTTPFound(location=request.route_url('consulta'))
except DBAPIError:
return Response("ERRO DB")
else:
print('NAO PASSOU')
return {'save_url': save_url,'project': 'tutorial'}
|
Conforme visto acima, a view denominada ‘cadastrar’ renderiza o template ‘templates/cad.pt’. A função cadastrar trata das requisições e respostas desta URI (Entende-se como caminho de uma URL, por exemplo: http://localhost/videos/cadastrar ) Observe que, se existem parâmetros na requisição, o sistema tenta cadastrar um video novo. Se não há parâmetros, simplesmente exibe o formulário para inclusão de um novo vídeo.
Observe que, em cada view, o ‘return’ sempre retorna as variáveis que vão para o template. Por exemplo, na função cadastrar() definimos que ‘save_url’ será equivalente ao valor da variável local save_url ( return {‘save_url’: save_url}). Por isso, tal valor é acessível no template abaixo( <form action=”${save_url}” method=”GET”> )
Arquivo de template: templates/cad.pt (Trecho relevante )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <div class="content">
<h1><span class="font-semi-bold">Cadastro de vídeos</span></h1>
<form action="${save_url}" method="GET">
<label>Nome:<br>
<input type="text" name="nome" value="" /><br>
</label>
<label>Descricao:<br>
<input type="text" name="descricao" value="" /><br>
</label>
<label>Preco:<br>
<input type="text" name="preco" value="" /><br>
</label>
<label>
<input type="submit" value="Cadastrar" style="margin-top: 1.2em;">
</label>
</form>
</div>
|
No meio de um grande código HTML, entre tags HTML e BODY, depois da tag HEAD, segue acima o que realmente nos interessa.
Consulta¶
Arquivo __init__.py
1 2 | def videos_include(config):
config.add_route('consulta', '/')
|
Agora, no trecho acima, foi configurada nova rota. Ou seja, quando digitarmos na barra de endereço “videos/”, seremos redirecionados para a view ‘consulta’. A configuração desta view segue abaixo:
Arquivo views.py
1 2 3 4 5 6 | @view_config(route_name='consulta',renderer='templates/consulta.pt')
def consulta(request):
videos = DBSession.query(Video).all()
url_edit = request.route_url('edicao')
url_cad = request.route_url('cadastrar')
return {'videos': videos,'url_edit': url_edit,'url_cad': url_cad}
|
Conforme código acima, eu busco todos os registros da tabela video, para exibi-los numa listagem.
Arquivo de template: ‘templates/consulta.pt’ (Trecho relevante)
1 2 3 4 5 6 7 8 9 10 11 12 | <div class="content">
<h1>Listagem de vídeos</h1>
<a tal:attributes="href string:${url_cad}"><button>CADASTRAR</button></a>
<div tal:repeat="item videos">
<div class="vido">
<a tal:attributes="href string:${url_edit}?&id=${item.id} "><strong>Nome: </strong><span tal:content="string:${item.name}" /></a><br />
<strong>Descricao: </strong><span tal:content="string:${item.descricao}" /><br />
<strong>Preco: </strong><span tal:content="string:${item.preco}" /><br />
</div>
</div>
</div>
</div>
|
Acima, a listagem de vídeos.
Edição¶
Arquivo __init__.py
1 2 | def videos_include(config):
config.add_route('edicao', '/editar')
|
Segue acima, a configuração da rota ‘videos/editar’.
Arquivo views.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @view_config(route_name='edicao',renderer='templates/edicao.pt')
def editar(request):
save_url = request.route_url('edicao')
dell = request.route_url('exclusao')
id = request.params['id']
video = DBSession.query(Video).filter_by(id=id).one()
if 'nome' in request.params.keys():
try:
print("PASSOU")
nome = request.params['nome']
descricao=request.params['descricao']
preco=request.params['preco']
dados = DBSession.query(Video).filter_by(id=id).update({'name': nome,'descricao': descricao,'preco': preco})
return HTTPFound(location=request.route_url('consulta'))
except Exception:
return Response('ERRO DB')
else:
print("nao passou")
return {'save_url': save_url,'video': video,'dell': dell}
|
Nesta view, verifica se existem parâmetros que identifiquem que a requisição se refere á submissão de um formulário. Se sim, é feita a atualização do video em questão, identificado pelo atributo ‘id’. Se não, é carregado um formulário com os campos para edição do registro.
Arquivo de template: ‘templates/edicao.pt’ (Trecho relevante)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <div class="content">
<h1><span class="font-semi-bold">EDICAO</span> <span class="smaller">Videos</span></h1>
<form action="${save_url}" method="GET">
<label>Nome:<br>
<input type="text" name="nome" value="${video.name}" /><br></label>
<label>Descricao:<br>
<input type="text" name="descricao" value="${video.descricao}" /><br>
</label><label>Preco:<br>
<input type="text" name="preco" value="${video.preco}" /><br>
</label>
<label>
<input tal:attributes="type string:hidden; name string:id; value string:${video.id}">
<input type="submit" value="Editar" style="margin-top: 1.2em;">
<a tal:attributes="href string:${dell}?id=${video.id}"><input type="button" value="Excluir" style="margin-top: 1.2em;"></a>
</label>
</form>
</div>
|
Segue acima, exibição dos campos do video, para atualização.
Exclusão¶
Arquivo __init__.py
1 2 | def videos_include(config):
config.add_route('exclusao', '/excluir')
|
Configuração de rota para ‘videos/excluir’
Arquivo views.py
1 2 3 4 5 6 7 8 9 10 11 | @view_config(route_name='exclusao')
def excluir(request):
if request.params:
try:
id=request.params['id']
DBSession.delete(DBSession.query(Video).filter_by(id=id).first())
return HTTPFound(location=request.route_url('consulta'))
except Exception:
return Response("ID INVALIDO")
else:
return Response("KD O ID?")
|
Se existir algum parâmetro ‘id’ na requisição, o video referenciado é excluido. Se não existir vídeo identificado pelo ‘id’, então, o sistema exibe a seguinte mensagem: ‘ID INVALIDO’. Se não existir nenhum parâmetro ‘id’, então, é exibido a seguinte mensagem: “KD O ID?”.
Rodando a aplicação¶
Para rodar a aplicação, você deve acessar o diretório-raíz de seu ambiente virtual (No nosso exemplo, dentro da pasta egito). Aí, considerando que você também está usando o Centos 7, execute o seguinte comando:
bin/pserve tutorial/development.ini
Aparecerá uma saída semelhante á esta:
Starting server in PID 11533. serving on http://0.0.0.0:6543
A saída acima indica que a aplicação está acessível na porta 6543. Mas, porta de onde? Da máquina que está hospedando esta aplicação. Caso seja sua máquina local, então, para testar, é só digitar na sua barra de endereço: http://localhost:5432/videos/.
Lidando com templates¶
O framework Pyramid utiliza as seguintes linguagens para template: TAL, METAL e Mako. Estas linguagens podem ser usadas em conjunto. No nosso exemplo, é usada apenas a linguagem TAL, para acessar o valor de algumas variáveis e realizar iterações em algumas listagens. Linguagem de template é a linguagem utilizada para programar em arquivos estáticos (em formato HTML), por exemplo.