Na primeira parte deste tutorial nós fizemos o “Frontend”. A interface gráfica está pronta, agora precisamos codificar o comportamento que elemento (objeto/widget) terá. Nesta parte faremos a interação com o banco de dados (SQLite)…
Apenas para lembrar, queremos fazer uma aplicação parecida com esta:
Índice:
- Parte 01: Frontend;
- Parte 02: Backend <[Você está aqui];
- Parte 03: Ligando o Backend com o Frontend;
- Parte 04: Compilando para Windows/Mac.
Parte 02_ Backend;
Nesta parte, precisaremos criar o CRUD (Create, Read, Update e Delete) além, é claro, de criar o banco em si.
Para esta aplicação, precisamos apenas de uma tabela (que se chamará clientes), com os seguintes campos:
- Id
- Nome
- Sobrenome
- CPF
O SQLite faz esta tarefa ser bem simples…
import sqlite3 database = "clientes.db" conn = sqlite3.connect(database) cur = conn.cursor() cur.execute("CREATE TABLE IF NOT EXISTS cliente (id INTEGER PRIMARY KEY , nome TEXT, sobrenome TEXT, email TEXT, cpf TEXT)") conn.commit() conn.close()
O fonte acima se conecta ao banco de dados ‘clientes.db’ e cria a tabela cliente, caso não exista. Neste exemplo, ele será um arquivo no diretório da aplicação.
Ao indicar que o campo id é uma PRIMARY KEY, ela já será definida como auto-increment.
Crie um arquivo chamado Backend.py e importe a biblioteca sqlite3:
import sqlite3 as sql
Sempre que utilizarmos o banco de dados, precisaremos repetir 4 linhas de código:
#Conectando ao bano de daods... conn = sqlite3.connect(database) cur = conn.cursor() #... Ações usando o banco... #Fazendo commit e desconecta do banco... conn.commit() conn.close()
Estas linhas vão ser sempre iguais e eu não sou muito fã de ficar repetindo código, então vamos encapsular estas lógicas…. mas temos um problema: Ao acessar o banco, temos duas variáveis: A de conexão (conn) e o cursor (cur).
Uma das maneiras de fazer isso é criar uma classe que contenha toda essa lógica… Existem formas mais elegantes de se fazer isso, mas quero manter as coisas simples para este tutorial. (Depois farei uma outra série de posts falando sobre Orientação a Objetos no Python…)
Nossa classe que cuidará da conexão com o banco e das operações será chamada de TransactionObject:
class TransactionObject(): database = "clientes.db" conn = None cur = None connected = False def connect(self): TransactionObject.conn = sql.connect(TransactionObject.database) TransactionObject.cur = TransactionObject.conn.cursor() TransactionObject.connected = True def disconnect(self): TransactionObject.conn.close() TransactionObject.connected = False def execute(self, sql, parms = None): if TransactionObject.connected: if parms == None: TransactionObject.cur.execute(sql) else: TransactionObject.cur.execute(sql, parms) return True else: return False def fetchall(self): return TransactionObject.cur.fetchall() def persist(self): if TransactionObject.connected: TransactionObject.conn.commit() return True else: return False
Esta classe possui funções:
- connect(): realiza conexão com o banco de dados
- disconnect(): fecha a conexão com o banco de dados
- execute(self, sql, parms): executa um comando no banco de dados. recebe três parâmetros:
- self: referencia para o próprio objeto. não precisa ser informado;
- sql: comando SQL a ser executado;
- parms: vetor com os parâmetros do comando SQL. Pode ser omitido.
- fetchall(): recupera os valores recebidos de um comando select.
- persist(): realiza o commit das operações realizadas.
Quando a aplicação for executada pela primeira vez, precisaremos criar o banco de dados:
def initDB(): trans = TransactionObject() trans.connect() trans.execute("CREATE TABLE IF NOT EXISTS clientes (id INTEGER PRIMARY KEY , nome TEXT, sobrenome TEXT, email TEXT, cpf TEXT)") trans.persist() trans.disconnect() initDB()
No fonte acima definimos a função initDB() e fazemos uma chamada a ela logo depois. Isso fará com que a aplicação chame esta função sempre que for iniciada. Ela se conecta ao banco de dados e cria a tabela de clientes, caso não exista. Desta forma, sempre que a aplicação for executada, ela irá verificar se o banco existe ou não e toma as providências necessárias. Isso de forma transparente para o usuário.
Agora vamos começar a construir as funções que serão utilizadas pelo Frontend. A primeira delas é a view(), a função que vai recuperar todos os dados do banco.
def view(): trans = TransactionObject() trans.connect() trans.execute("SELECT * FROM clientes") rows = trans.fetchall() trans.disconnect() return rows
A próxima é a função que insere novos registros no banco:
def insert(nome, sobrenome, email, cpf): trans = TransactionObject() trans.connect() trans.execute("INSERT INTO clientes VALUES(NULL, ?,?,?,?)", (nome, sobrenome, email, cpf)) trans.persist() trans.disconnect()
Agora vamos fazer a função de busca, que será realizada utilizando o operador OR e todos os campos que não forem preenchidos pelo usuário na hora da busca serão considerados como strings vazias…
def search(nome="", sobrenome="", email="", cpf=""): trans = TransactionObject() trans.connect() trans.execute("SELECT * FROM clientes WHERE nome=? or sobrenome=? or email=? or cpf=?", (nome,sobrenome,email, cpf)) rows = trans.fetchall() trans.disconnect() return rows
A função de atualização é a próxima a ser criada:
def update(id, nome, sobrenome, email, cpf): trans = TransactionObject() trans.connect() trans.execute("UPDATE clientes SET nome =?, sobrenome=?, email=?, cpf=? WHERE id = ?",(nome, sobrenome,email, cpf, id)) trans.persist() trans.disconnect()
Por último, vamos fazer a função para remover registros:
def delete(id): trans = TransactionObject() trans.connect() trans.execute("DELETE FROM clientes WHERE id = ?", (id,)) trans.persist() trans.disconnect()
As operações encapsuladas são todas bem simples, quase sempre seguindo a sequencia: operação no banco de dados, commit e desconecta. Uma aplicação do mundo real seria mais complexa e possuiria lógicas de tratamento de erros e rollbacks, quando necessário.
Nesta seção criamos as funções que serão utilizadas no Frontend. Elas já estão funcionais e podem ser utilizadas através de script, mas ainda não estão interagindo com a parte gráfica e este é o próximo passo.
Latest posts by Breno RdV (see all)
- O que é Metaclass e como ela funciona. (#python #dev #metaclass) - janeiro 11, 2023
- Entenda a mágica dos Generators. (#python, #dev, #generator, #iterator) - dezembro 28, 2022
- Ordenando um DataFrame por múltiplas colunas. (#python #pandas #jupyter #dev #data) - agosto 3, 2022
Pingback: Tutorial: Aplicação em Python + SQLite (Parte 01) – Raccoon Ninja
Pingback: Tutorial: Aplicação em Python + SQLite (Parte 04) – Raccoon Ninja
Pingback: Tutorial: Aplicação em Python + SQLite (Parte 03) – Raccoon Ninja