Tutorial: Aplicação em Python + SQLite (Parte 02)

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:

Cadastro de Clientes em Python

Cadastro de Clientes em Python

Índice:

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
  • Email
  • 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.

The following two tabs change content below.
Arquiteto de Software e Desenvolvedor Backend (quase Fullstack), geralmente trabalho com C#, PowerShell, Python, Golang, bash e Unity (esse é mais por hobby). Estou sempre buscando algo novo para aprender, adicionando novas ferramentas ao meu cinto de utilidades.
Posted in Dev, Python and tagged , , , , , , , , .