tabela - Assembla
Transcrição
tabela - Assembla
Parte VI Luiz Eduardo Borges Sumário (parte VI) • Banco de dados: • DBI. • ORM. • Web. • MVC. • XML. SGBD (I) ● ● Sistemas Gerenciadores de Banco de Dados (SGBDs) são reconhecidos por prover uma forma de acesso consistente e confiável para informações. A maioria dos SGDB atuais são baseados no modelo relacional, no qual as informações são representadas na forma de tabelas. Geralmente, estas tabelas podem ser consultadas através de uma linguagem especializada para isso, chamada SQL (Structured Query Language). SGBD (II) ● ● Geralmente, os SGBDs utilizam a arquitetura clienteservidor. Os aplicativos usam a API cliente para poder se comunicar com o servidor, que é o responsável por receber as consultas dos clientes, interpretar as sentenças SQL e recuperar os dados com um tempo de resposta adequado. Para fazer isso, o servidor precisa realizar uma série de outras tarefas, tais como: verificar credenciais, controlar o acesso, gerenciar conexões de rede, manter a integridade dos dados, otimizar as consultas e resolver questões de concorrência. SGBD Cliente / Servidor Servidor Cliente Aplicativo API Cliente Rede Processo Processo Arquivos Arquivos Arquivos Modelo relacional (I) ● ● ● ● Modelo de dados baseado em lógica e na teoria de conjuntos. A relação é representada na forma de uma tabela. Cada tabela é composta por atributos (colunas) e tuplas (linhas). Domínio é o conjunto de valores que um atributo pode assumir. Visão (view) é uma tabela virtual, que mostra atributos de outras tabelas relacionadas. Modelo relacional (II) ● ● ● ● Cada tupla de uma tabela tem que estar associada a uma chave única que permita identifica-la. Uma chave pode estar composta por um ou mais atributos. Chave primária (Primary Key): é o valor ou conjunto de valores que identificam uma fila dentro de uma tabela. Nunca pode ser NULL. Chave estrangeira (Foreign Key): é o valor de uma tabela que corresponde ao valor da chave primária em outra tabela. Esta chave representa as relações entre as tabelas. Modelo relacional (III) Tabela Amostras ID Local Densidade Data 1 3 2.3 12-12-2012 2 3 1.4 01-03-1999 3 2 0.3 04-04-2010 4 5 0.9 18-11-2009 5 4 0.5 31-07-2002 6 4 3.1 null Chave primária Chave estrangeira Atributos Tuplas SQL ● ● ● SQL (Structured Query Language) é a linguagem para consultas mais usada em SGBDs, com algumas variações. O SGBD interpreta as sentenças SQL, criando um plano de execução, que ele define como os dados serão obtidos, tornando transparente ao usuário a parte física (estruturas de dados, índices, metadados, restrições de integridade e sistema de arquivos). DDL (Data Definition Language) é usada para descrever as estruturas de dados. SQL (select) Sintaxe básica: # sqlite3 music.db select <lista de atributos> SQLite version 3.5.8 from <lista de tabelas> Enter ".help" for instructions where <condição> sqlite> select artist,title ...> from discs ...> where genre = 'Progressive Rock' ...> and year = 1974 order by 1, 2; Genesis|Live Genesis|The Lamb Lies Down On Broadway (Disc 1) Genesis|The Lamb Lies Down On Broadway (Disc 2) Jethro Tull|WarChild King Crimson|Red King Crimson|Starless And Bible Black Yes|Relayer DDL (create) # sqlite3 livros.db SQLite version 3.5.8 Enter ".help" for instructions sqlite> create table livros ...> (id integer primary key, ...> titulo varchar(100) not null, ...> autor varchar(100) not null, ...> edicao integer default 1, ...> data date default (datetime())); Sintaxe básica: create table <tabela> (<coluna1> <definição>, ... <colunaN> <definição>) No SQLite, para listar as tabelas: .tables Para listar a estrutura da tabela: .schema <tabela> SQL (insert) sqlite> insert into livros ...> (titulo, autor) ...> values ('Python para Desenvolvedores', ...> 'Luiz Eduardo Borges'); Sintaxe básica: Insert into <tabela> (<lista de atributos>) values (<lista de valores>) Os atributos não informados serão completados com os valores default. SQL (delete) sqlite> delete from livros; Sintaxe básica: delete from <tabela> where <condição> DBI Interpretador Programa As consultas são sentenças SQL e as respostas são listas de tuplas ou dicionários. O módulo DBI (Database Interface) é um driver especifico para o SGBD. DBI SGBD DBI (exemplo) import MySQLdb Módulo DBI para MySQL. con = MySQLdb.connect(db='test', user='root', passwd='') cur = con.cursor() Cria um cursor para a conexão. cur.execute('show databases') recordset = cur.fetchall() for record in recordset: print record con.close() Executa SQL diretamente. Retorna os registros como uma lista de tuplas. Fecha a conexão. SQLite (exemplo / I) # -*- coding: utf-8 -*import sqlite3 # Cria uma conexão e um cursor con = sqlite3.connect('emails.db') cur = con.cursor() # Cria uma tabela sql = 'create table emails '\ '(id integer primary key, '\ 'nome varchar(100), '\ 'email varchar(100))' cur.execute(sql) Continua... SQLite (exemplo / II) # sentença SQL para inserir registros sql = 'insert into emails values (null, ?, ?)' # Dados recset = [('jane doe', '[email protected]'), ('rock', '[email protected]')] # Insere os registros for rec in recset: cur.execute(sql, rec) # Confirma a transação con.commit() Continua... SQLite (exemplo / III) # Seleciona todos os registros cur.execute('select * from emails') # Recupera os resultados recset = cur.fetchall() # Mostra for rec in recset: print '%d: %s(%s)' % rec # Fecha a conexão con.close() Saída: 1: jane doe([email protected]) 2: rock([email protected]) PostgreSQL (exemplo / I) # -*- coding: latin1 -*import psycopg2 # Para bancos de dados locais (via Unix Domain Sockets) #con = psycopg2.connect(database='music') # Via TCP/IP con = psycopg2.connect(host='localhost', database='music', user='pg', password='xXxXx') cur = con.cursor() # Cria uma tabela sql = 'create table tracks '\ '(id serial primary key, '\ 'track varchar(100), '\ 'band varchar(100))' cur.execute(sql) Continua... PostgreSQL (exemplo / II) # A interpolação usa uma notação semelhante a do Python sql = 'insert into tracks values (default, %s, %s)' # Dados recset = [('Kashmir', 'Led Zeppelin'), ('Starless', 'King Crimson')] # Insere os registros for rec in recset: cur.execute(sql, rec) con.commit() # Recupera os registros cur.execute('select * from tracks') recset = cur.fetchall() # Mostra Saída: for rec in recset: (1, 'Kashmir', 'Led Zeppelin') print rec (2, 'Starless', 'King Crimson') con.close() cx_oracle (exemplo / I) # Driver DBI import cx_Oracle # Conecta no banco con = cx_Oracle.connect('hr/ko9lp0@localhost') cur = con.cursor() # Pega a data do SGBD cur.execute('select sysdate from dual') print cur.fetchall() Saída: [(datetime.datetime(2009, 5, 15, 10, 54),)] # Cria tabela sql = 'create global temporary table ascii (n integer, t varchar(50))' cur.execute(sql) Continua... cx_oracle (exemplo / II) # Preenche a tabela for i in xrange(128): cur.execute('insert into ascii values (:a, :b)', a=i, b=chr(i)) # Consulta a tabela cur.execute('select * from ascii') print cur.fetchall() # Remove a tabela cur.execute('drop table ascii') # Desconecta con.close() Saída: [(0, '\x00'), (1, '\x01'), (2, '\x02'), ... (125, '}'), (126, '~'), (127, '\x7f')] ORM (Object Relational Mapper) Interpretador Programa As consultas são métodos e as respostas são objetos. O módulo ORM desacopla a aplicação do SGBD. ORM SGBD DBI SQLAlchemy (exemplo / I) # -*- coding: latin1 -*from sqlalchemy import * # URL => driver://username:password@host:port/database db = create_engine('mysql://root@localhost/test') # Torna acessível os metadados metadata = MetaData(db) # Ecoa o que SQLAlchemy está fazendo metadata.bind.echo = True Continua... SQLAlchemy (exemplo / II) # Tabela Prog prog_table = Table('progs', metadata, Column('prog_id', Integer, primary_key=True), Column('name', String(80))) # Cria a tabela prog_table.create() # Carrega a definição da tabela prog_table = Table('progs', metadata, autoload=True) # Insere dados i = prog_table.insert() i.execute({'name': 'Yes'}, {'name': 'Genesis'}, {'name': 'Pink Floyd'}, {'name': 'King Crimson'}) Continua... SQLAlchemy (exemplo / III) # Seleciona s = prog_table.select() r = s.execute() for row in r.fetchall(): print row Saída: (1L, 'Yes') (2L, 'Genesis') (3L, 'Pink Floyd') (4L, 'King Crimson') Web A Web dinâmica é uma forma de execução remota. Servidor Requisição GET ou POST Browser HTTPd Resposta url?param=arg => url(param=arg) CherryPy import cherrypy class Root(object): @cherrypy.expose def index(self): return 'Hello World!' cherrypy.quickstart(Root()) A classe será a raiz do servidor. O método será publicado. Inicia o servidor. CherryTemplate from cherrytemplate import renderTemplate progs = ['Yes', 'Genesis', 'King Crimson'] template = '<html>\n<body>\n'\ '<py-for="prog in progs">'\ ' <py-eval="prog"><br>\n'\ '</py-for>'\ '</body>\n</html>\n' print renderTemplate(template) <html> <body> Yes<br> Genesis<br> King Crimson<br> </body> </html> CherryPy + CherryTemplate import cherrypy from cherrytemplate import renderTemplate class Root(object): @cherrypy.expose def index(self): progs = ['Yes', 'Genesis', 'King Crimson'] return renderTemplate(file='template.html') cherrypy.quickstart(Root()) Arquivo de template. MVC MVC: Model View Controller Recupera dados e apresenta ao usuário. Controller View Recebe e reage a eventos. Model Encapsula os dados da aplicação e a lógica de domínio. MVC (exemplo / I) #!/usr/bin/env python # -*- coding: utf-8 -*"""Exemplo MVC""" # CherryPy import cherrypy # CherryTemplate from cherrytemplate import renderTemplate # ZODB from ZODB import FileStorage, DB from persistent import Persistent import transaction Continua... MVC (exemplo / II) # Classe persistente class Animal(Persistent): """Classe de animais""" pass # Banco de dados Zoo storage = FileStorage.FileStorage('zoo.fs') db = DB(storage) conn = db.open() zoo = conn.root() Continua... MVC (exemplo / III) class Root(object): """Raíz do site""" @cherrypy.expose def index(self): """Lista de animais do Zoo""" return renderTemplate(file='index.html') @cherrypy.expose def add(self): """Cadastra novos animais""" return renderTemplate(file='add.html') Continua... MVC (exemplo / IV) @cherrypy.expose def save(self, animal): """Salva o animal""" if animal: new = Animal() new.id = animal new.name = animal zoo[new.id] = new transaction.commit() return renderTemplate(file='index.html') # Inicia o servidor cherrypy.quickstart(Root()) XML Árvore de elementos Canino Lobo Coiote Raiz Raposa Elementos Cachorro Nome: Bandit Raça: Labrador Cor: Branco Atributos XML (estrutura) Elemento <Lobo>...</Lobo> Lobo Cachorro Tag Nome: Bandit Raça: Labrador Cor: Branco Atributos <Cachorro cor="Branco" nome="Bandit" raca="Labrador" /> ElementTree (escrita) from xml.etree.ElementTree import Element, ElementTree root = Element('Canino') Criando os elementos. lobo = Element('Lobo') raposa = Element('Raposa') coiote = Element('Coiote') cachorro = Element('Cachorro', nome='Bandit', raca='Labrador', cor='Branco') root.append(lobo) root.append(raposa) lobo.append(coiote) lobo.append(cachorro) ElementTree(root).write('caninos.xml') Preenchendo a árvore. Salvando o arquivo. XML (arquivo) <Canino> <Lobo> <Coiote /> <Cachorro cor="Branco" nome="Bandit" raca="Labrador" /> </Lobo> <Raposa /> </Canino> ElementTree (leitura) from xml.etree.ElementTree import ElementTree tree = ElementTree(file='caninos.xml') root = tree.getroot() # Lista os nós abaixo do root print root.getchildren() # Encontra o lobo lobo = root.find('Lobo') # Encontra o cachorro cachorro = lobo.find('Cachorro') print cachorro.tag, cachorro.attrib # Remove a raposa root.remove(root.find('Raposa')) print root.getchildren() Exercícios da parte VI (I) • Implementar uma classe Animal com os atributos: nome, especie, gênero, peso, altura e idade. O objeto derivado desta classe deverá salvar seu estado em arquivo com um método chamado “salvar” e recarregar o estado em um método chamado “desfazer”. Exercícios da parte VI (II) • Implementar uma aplicação Web com uma saudação dependente do horário (exemplos: “Bom dia, são 09:00.”, “Boa tarde, são 13:00.” e “Boa noite, são 23:00.”) Respostas da parte VI (I) import pickle class Animal(object): attrs = ['nome', 'especie', 'genero', 'peso', 'altura', 'idade'] def __init__(self, **args): for attr in self.attrs: setattr(self, attr, args.get(attr, None)) def __repr__(self): dic_attrs = {} for attr in self.attrs: dic_attrs[attr] = getattr(self, attr) return 'Animal: %s' % str(dic_attrs) Continua... Respostas da parte VI (II) def salvar(self): dic_attrs = {} for attr in self.attrs: dic_attrs[attr] = getattr(self, attr) pickle.dump(dic_attrs, file('a.pkl', 'w')) def desfazer(self): attrs = pickle.load(file('a.pkl')) for attr in attrs: setattr(self, attr, attrs[attr]) Continua... Respostas da parte VI (III) # Teste gato = Animal(nome='Tinker', especie='Gato', genero='m', peso=6, altura=0.30, idade=4) gato.salvar() gato.idade = 5 print gato gato.desfazer() print gato Saída: Animal: {'especie': 'Gato', 'genero': 'm', 'nome': 'Tinker', 'peso': 6, 'idade': 5, 'altura': 0.29999999999999999} Animal: {'especie': 'Gato', 'genero': 'm', 'nome': 'Tinker', 'peso': 6, 'idade': 4, 'altura': 0.29999999999999999} Respostas da parte VI (IV) # -*- coding: latin1 -*import time import cherrypy class Root(object): @cherrypy.expose def index(self): hour = '%02d:%02d' % time.localtime()[3:5] if '06:00' < hour <= '12:00': salute = 'Bom dia' elif '12:00' < hour <= '18:00': salute = 'Boa tarde' else: salute = 'Boa noite' return '%s, são %s.' % (salute, hour) cherrypy.quickstart(Root()) Fim da parte VI