Package: bravaorm
Brava ORM para MySQL/MariaDBSDK fornece uma série de recursos para aumentar produtividade no desenvolvimento de aplicações com integração a banco de dados relacional MySql/MariaDB.InstalaçãoInstalação utilizando PippipinstallbravaormGit/Clonegit clone https://github.com/robertons/bravaorm
cd bravaorm
pip install -r requirements.txt
python setup.py installDados de Entradaentradadefaulttipoobrigatóriodb_userNonestringsimNome Usuáriodb_passwordNonestringsimSenha Usuariodb_hostNonestringsimHostdb_portNonestringsimPortadb_databaseNonestringsimNome DBdb_sslFalsebooleannãoConexão Seguradb_ssl_caNonestringnãoCertificado CAdb_ssl_certNonestringnãoCertificadodb_ssl_keyNonestringnãoChave Certificadodb_charsetutf8stringnãoCharset DBlog_levelerrorstringnãoNível logSaídamétodoaplicávelresultadofirstConexãoobjeto de um selectallConexãolista de objetos de um selectfetchConexãolista  de um select sem conversão em objetodelete(obj)Conexãoexclui um objetosave()Conexãosalva operações no dbadd(obj)Objeto, Conexãoadiciona objeto a uma lista/tabelaToJSON()Objeto, Conexãoresultado em formato dictConexão com Banco de dadosimportbravaormconn=bravaorm.Connection(db_user="root",db_password="pass",db_host="host",db_port=3306,db_database="dbmae",db_charset="utf8mb4")Gerando Modelo de Entidadeimportosimportbravaormbravaorm.Make(dir=os.path.dirname(os.path.abspath(__file__)),db_user="user",db_password="pass",db_host="host",db_port=3306,db_database="dbname")O script acima irá gerar na raiz do projeto as classes objetos baseados no Banco de Dados. As tabelas do banco dedos devem seguir os requisitos de pluralização, conforme exemplo abaixo:.
├──...
├──model# Raiz Entidade│├──__init__.py│├──categoria.py# Classe Categoria | Tabela categorias│├──cliente.py# Classe Cliente  	| Tabela clientes│└──compra.py# Classe Compra  	| Tabela compras│└──produto.py# Classe Produto  	| Tabela produtos└──...Tomando como exemplo a tabela produtos, a classe gerada estará assim:# -*- coding: utf-8 -*-frombravaorm.entityimport*classProduto(Entity):def__init__(cls,**kw):cls.__metadata__={'pk':['id']}cls.id=Int(pk=True,auto_increment=True,not_null=True,precision=10,scale=0)cls.id_categoria=Int(fk=True,not_null=True,precision=10,scale=0)cls.prod_nome=String(max=155)cls.prod_preco=Decimal(not_null=True,precision=19,scale=2)cls.prod_data_fabricacao=DateTime(format='%d/%m/%Y')cls.prod_data_modificacao=DateTime(format='%d/%m/%Y HH:MM:SS')# One-to-Onecls.categorias=Obj(context=cls,keyname='categorias',name='Categoria',key='id',reference='id_categoria',table='categorias')# One-to-manycls.compras=ObjList(context=cls,keyname='compras',name='Compra',key='id_compra',reference='id',table='compras')super().__init__(**kw)Seleção de Objetos e Condiçõesproduto=conn.produtos.where("id=10").firstprint(produto)print(produto.toJSON())> <model.produto.Produto object at 0x101237c10>> {'id': 10, 'id_categoria': 10, 'prod_nome': 'Exemplo', 'prod_preco':  Decimal('99.90'), 'prod_data_fabricacao': datetime(2010, 12, 10, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 03, 31, 16, 54, 22)}Condição 'Ou'A condição orwhere é dependente de condição where, e cria novos blocos a cada utilização.produtos=conn.produtos.where("id=10").orwhere("id=12").orwhere("id=14").allprint(produtos.toJSON())> [{'id': 10, 'id_categoria': 10,  'prod_nome': 'Exemplo', 'prod_preco':  Decimal('99.90'), 'prod_data_fabricacao': datetime(2010, 12, 10, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 03, 31, 16, 54, 22)}, {'id': 12, 'prod_nome': 'Outro Exemplo ', 'prod_preco':  Decimal('88,20'), 'prod_data_fabricacao': datetime(2011, 10, 8, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 02, 12, 10, 24, 20)}, {'id': 14, 'prod_nome': 'Novo Exemplo', 'prod_preco':  Decimal('129,90'), 'prod_data_fabricacao': datetime(2009, 11, 7, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 01, 10, 14, 34, 15)}]Seleção de Camposproduto=conn.produtos.where("id=10").select("id, prod_nome").firstprint(produto.toJSON())> {'id': 10, 'prod_nome': 'Exemplo'}Alias de Funções ou Camposproduto=conn.produtos.alias('prod_nome','nome').where("id=10").firstprint(produto['nome'])print(produto.prod_nome)> Exemplo> ExemploAlias são campos não editáveisOrdenamento# ORDERBYproduto=conn.produtos.orderby("prod_nome").allproduto=conn.produtos.orderby("prod_nome DESC").allAgrupamento# GROUPBYproduto=conn.produtos.groupby("id_categoria").allLimite# LIMITproduto=conn.produtos.orderby("prod_nome").limit(0,10).allUnião de ObjetosO métodos "join" e "inner" são recomendados para uso de objetos com relacionamento "um para um",  ou em casos onde o resultado da tabela secundária irá retornar apenasum resultado.A utilização desses métodos em casos de seleção "um para vários" o resultado será baseado na tabela secundária, podendo ocorrer a repetição do objeto principal. Neste neste caso é recomendável a utilização do método "include" onde o resultado da lista será com objetos únicos incluindo os vários resultados da tabela secundária.Exemplos:JoinO método join, é equivalente ao "LEFT JOIN" e retorna o objeto principal incluindo a seleção secundária, de duas tabelas.produto=conn.produtos.join("categegorias").all> {'id': 10, 'id_categoria': 10, 'prod_nome': 'Exemplo', 'prod_preco':  Decimal('99.90'), 'prod_data_fabricacao': datetime(2010, 12, 10, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 03, 31, 16, 54, 22), 'categorias': {'id':1, 'cat_nome':'Categoria Teste'}}InnerO método inner, é equivalente ao "INNER JOIN" e retorna o objeto principal baseado na interceção da tabela secundária.produto=conn.produtos.inner("categorias").where("categorias.id=1").all> [{'id': 10, 'id_categoria': 10, 'prod_nome': 'Exemplo', 'prod_preco':  Decimal('99.90'), 'prod_data_fabricacao': datetime(2010, 12, 10, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 03, 31, 16, 54, 22), 'categorias': {'id':1, 'cat_nome':'Categoria Teste'}}, {'id': 12, 'prod_nome': 'Outro Exemplo ', 'prod_preco':  Decimal('88,20'), 'prod_data_fabricacao': datetime(2011, 10, 8, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 02, 12, 10, 24, 20), 'categorias': {'id':1, 'cat_nome':'Categoria Teste'}}, {'id': 14, 'prod_nome': 'Novo Exemplo', 'prod_preco':  Decimal('129,90'), 'prod_data_fabricacao': datetime(2009, 11, 7, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 01, 10, 14, 34, 15), 'categorias': {'id':1, 'cat_nome':'Categoria Teste'}}]IncludeO método include, faz seleção de um ou vários objetos relacionados ao objeto principal, recomendado para relacionamento um para vários.este método requer atenção em relação a performance para grandes seleçõesproduto=conn.produtos.include("compras").where("id=10, compras.compra_paga=1").all> [{'id': 10, 'id_categoria': 10, 'prod_nome': 'Exemplo', 'prod_preco':  Decimal('99.90'), 'prod_data_fabricacao': datetime(2010, 12, 10, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 03, 31, 16, 54, 22), 'compras': [{'id':1, 'compra_data':datetime(2010, 12, 10, 0, 0, 0), 'id_cliente':12}, {'id':23, 'compra_data':datetime(2017, 11, 13, 0, 0, 0), 'id_cliente':54}, {'id':34, 'compra_data':datetime(2018, 1 11, 0, 0, 0), 'id_cliente':20}, {'id':110, 'compra_data':datetime(2019, 7, 22, 0, 0, 0), 'id_cliente':16}]}]FetchO método fetch  permite o obter a resposta direta do DB em formato dict a partir de um select, sem a conversão dos dados em classe/objeto. Este método oferece ganho significativo de performance.# GROUPBYprodutos=conn.produtos.fetch> [{'id': 10, 'prod_nome': 'Exemplo', 'prod_preco':  Decimal('99.90'), 'prod_data_fabricacao': datetime(2010, 12, 10, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 03, 31, 16, 54, 22)}, {'id': 12, 'prod_nome': 'Outro Exemplo ', 'prod_preco':  Decimal('88,20'), 'prod_data_fabricacao': datetime(2011, 10, 8, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 02, 12, 10, 24, 20)}, {'id': 14, 'prod_nome': 'Novo Exemplo', 'prod_preco':  Decimal('129,90'), 'prod_data_fabricacao': datetime(2009, 11, 7, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 01, 10, 14, 34, 15)}]Método toJSON()O metodo toJSON() retorna o objeto ou lista de resultado em formato dict.print(produto)print(produto.toJSON())> <model.produto.Produto object at 0x107737c10>> {'id': 10, 'prod_nome': 'Exemplo', 'prod_preco':  Decimal('99.90'), 'prod_data_fabricacao': datetime(2010, 12, 10, 0, 0, 0), 'prod_data_modificacao': 'datetime(2021, 03, 31, 16, 54, 22)}Criação de ObjetosSimplesfrommodelimport*produto=Produto()produto.prod_nome='Exemplo'produto.prod_preco=Decimal('99.90')produto.prod_data_fabricacao=datetime(2010,12,10,0,0,0)produto.prod_data_modificacao='31/03/2021 16:54:22'# Conversão para datetime seguindo formato '%d/%m/%Y HH:MM:SS'conn.add(produto)conn.save()OUfrommodelimport*produto=Produto(prod_nome='Exemplo',prod_preco=Decimal('99.90'),prod_data_fabricacao=datetime(2010,12,10,0,0,0),prod_data_modificacao='31/03/2021 16:54:22')conn.add(produto)conn.save()OUfrommodelimport*produto=Produto(**{prod_nome:'Exemplo',prod_preco:Decimal('99.90'),prod_data_fabricacao:datetime(2010,12,10,0,0,0),prod_data_modificacao:'31/03/2021 16:54:22'})conn.add(produto)conn.save()Com RelacionamentosNo exemplo abaixo, criamos um produto na tabelaprodutoscom 3 fotos na tabelaprodutos_fotosfrommodelimport*produto=Produto()produto.prod_nome='Exemplo'produto.prod_preco=Decimal('99.90')produto.prod_data_fabricacao=datetime(2010,12,10,0,0,0)produto.prod_data_modificacao='31/03/2021 16:54:22'# Conversão para datetime seguindo formato '%d/%m/%Y HH:MM:SS'foto=ProdutoFoto()foto.foto_descricao='Vista Frontal'foto.foto_arquivo='fronta.jpg'produto.produtos_fotos.add(foto)foto=ProdutoFoto(**{foto_descricao:'Vista Lateral',foto_arquivo:'lateral.jpg'})produto.produtos_fotos.add(foto)produto.produtos_fotos.add(ProdutoFoto(foto_descricao='Vista Lateral',foto_arquivo='lateral.jpg'))conn.add(produto)conn.save()Atualizando Objetoproduto=conn.produtos.where("id=10").firstproduto.prod_preco=Decimal(89.90)conn.add(produto).save()ou váriosprodutos=db.produtos.where("prod_preco>=100").allforprodutoinprodutos:produto.prod_preco=produto.prod_preco*0.9conn.add(produto)db.save()ou relativoscategoria=db.categorias.include("produtos").where("id=1, produtos.pro_preco>=100").allforprodutoincategoria.produtos:produto.prod_preco=produto.prod_preco*0.9conn.add(produto)db.save()Exclusão de ObjetosO método requer um objeto de entrada, ou uma condição where definida:conn.delete(produto).save()ou condicionalconn.produtos.where("prod_preco=100").delete()Contadorquantidade_produtos=conn.produtos.where("prod_preco=100").countprint(quantidade_produtos)**> 113 **Update QueryRealizar Atualização de registros com condição.Atualizando um campoconn.produtos.where("prod_active=0").set("prod_active",1)Atualizando um ou mais camposconn.produtos.where("prod_active=0").update({"prod_active":1,"prod_promo":1})Execute QueryÉ possível executar queries mais complexas e com condicionais específicas, nesse caso é possível escrever a query diretamente na conexão e informar qual o tipo de objeto será retornado a partir dela.A definição do objeto é opcional.produtos=conn.execute("SELECT * FROM produtos WHERE preco > 100","Produto")A consulta acima irá retornar uma lista de  objetosProdutoprodutos=conn.execute("SELECT * FROM produtos WHERE preco > 100")A consulta acima irá retornar uma lista com dictionary  com dados de produtosLicenseMITCopyright (c) 2019-2021 Roberto Neves. All rights reserved. info (at)robertonsilva@gmail.com