Que tal se você pudesse organizar seus objetos de banco de dados (por exemplo, tabelas e visualizações) em namespaces de acordo com seus papéis no sistema?
Neste artigo veremos a maneira correta de lidar com esquemas PostgreSQL no Django e algumas pequenas dicas sobre Modelos Django e Python.
Esquema
Também conhecido como namespace, schema é um tipo de objeto de banco de dados cuja finalidade é ser uma camada de organização hierárquica que fica logo abaixo de um banco de dados.
No PostgreSQL, “público” é o esquema padrão, mas você pode criar seu próprio namespaces para organizar outros tipos de objetos, como tabelas, visualizações, funções e etc.
Hierarquia de objetos de banco de dados
- Servidor |- Instância PostgreSQL (porta 5432 por padrão) |- Função (Usuários e Grupos) |- Tablespace |- Banco de Dados |- Trigger |- Extensão |- Idioma |- Schema |- Tabela |- View |- Materialized Ver |- Sequência |- Função |- Procedimento
Sobre nosso laboratório
Esse é um laboratório simples com Django em ambiente virtual (com virtualenv) e PostgreSQL instalado em localhost.
- Python 3.8
- Django 3.0
- PostgreSQL 12
Deve funcionar com muitas versões mais antigas 🙂
Códigos
- > SQL (psql);
- $ shell (Linux, FreeBSD, Unix*);
- >>> shell Python.
Prática
-
PostgreSQL
A estrutura do banco de dados é a primeira coisa que faremos.
- Criação de usuário de banco de dados para o aplicativo;
- Criação de banco de dados;
- Criação de esquema;
- Criação de tabela
Vamos criar nosso próprio exemplo na ferramenta de linha de comando integrada do psql:
$ psql
Criação do aplicativo do usuário:
CREATE ROLE user_test SENHA ENCRIPTADA '123' LOGIN;
A função de banco de dados foi criada com uma senha criptografada e um atributo de login (usuário).
Criação de banco de dados para testes:
> CRIAR BANCO DE DADOS db_test PROPRIETÁRIO user_test;
O banco de dados é de propriedade de “user_test”.
Conecte-se a ele como usuário “user_test”:
> \c db_test user_test
Dentro do nome de usuário do banco de dados psql shell \c.
Criação de um esquema:
> CRIAR ESQUEMA ns_hr;
O namespace para nosso exemplo está pronto!
Mostrar todos os esquemas que não são catálogos:
> SELECTnspname AS namespaceFROM pg_catalog.pg_namespaceWHERE nspname !~ '(^pg_|information_schema)';
Saída:
namespace ----------- public ns_hr
Observe que aparece o namespace padrão (público) e o ns_hr, criado para nosso laboratório.
Criação de uma tabela no esquema ns_hr:
> CREATE TABLE ns_hr.tb_person( id_ chave primária serial, texto do nome não nulo, texto do sobrenome não nulo);
Uma mesa simples…
Pressione
<Ctrl> + D
sair. -
Django
É hora de codificar em Python! 😀
- Ambiente virtual;
- Instalação de módulos Python;
- Criação e configuração do projeto Django;
- Criação de aplicativo Django;
- Criação do modelo Django;
- Migrações;
- Testes em shell;
Criação de ambiente virtual:
$ virtualenv -p `which python3.8` django
O caminho absoluto do binário do Python 3.8 foi indicado como interpretador Python deste ambiente.
Acesse o diretório do ambiente e ative-o:
$ cd django &&source bin/activate
Seu prompt mudou, começou em “(django)” indicando que seu ambiente virtual foi ativado.
Instale os módulos necessários para nossos testes:
$ pip install django psycopg2-binary configobj ipython
Respectivamente:framework web Django, driver PostgreSQL, leitor de arquivos de configuração e shell interativo aprimorado.
Criação de novo projeto Django:
$ django-admin startproject my_project
Renomeie o diretório do projeto para src:
$ mv my_project src
Isso é para facilitar a hierarquia de diretórios e não afetará os resultados. É porque tem um diretório de mesmo nome que pode causar alguma confusão…
Criação do arquivo de configuração do banco de dados:
$ cat <src/my_project/db.confDB_HOST ='localhost'DB_NAME ='db_test'DB_USER ='user_test'DB_PASSWORD ='123'DB_PORT =5432EOF
Aqui criamos um arquivo de configuração separado para a conexão com o banco de dados.
Edite o arquivo de configuração principal do projeto:
$ vim src/my_project/settings.py
importar osfrom configobj import ConfigObj
Abaixo das importações adicione uma linha que traz a classe ConfigObj.
# Database# https://docs.djangoproject.com/en/2.2/ref/settings/#databases# Local do arquivo de configuração do banco de dadosDB_CONF_FILE =f'{BASE_DIR}/my_project/db.conf'# Leia as configurações do arquivoDB_CONFIG =ConfigObj(DB_CONF_FILE)# Parâmetros de conexão do banco de dadosDB_HOST =DB_CONFIG['DB_HOST']DB_NAME =DB_CONFIG['DB_NAME']DB_USER =DB_CONFIG['DB_USER']DB_PASSWORD =DB_CONFIG['DB_PASSWORD']DB_PORT =DB_CONFIG['DB_PORT']DATABASES ={ 'default':{ 'ENGINE':'django.db.backends.postgresql', 'NAME':DB_NAME, 'USER':DB_USER, 'PASSWORD':DB_PASSWORD, 'HOST':DB_HOST, 'PORT':DB_PORT, } }
Modifique a “sessão” do banco de dados como acima.
Criação de links simbólicos para manage.py:
$ ln -s `pwd`/src/manage.py `pwd`/bin/manage.py
Para facilitar nosso trabalho criamos um link simbólico para manage.py no diretório bin que está em nosso $PATH.
Executar servidor web virtual:
$ manage.py runserver 0.0.0.0:8000
Teste no seu navegador:http://localhost:8000 e depois
Acessar o diretório do projeto:
$ cd src
Vamos verificar os arquivos dentro do diretório atual:
$ árvore .
Saída:
.├── manage.py└── my_project ├── db.conf ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-38.pyc │ ├── settings .pyc │ ├── urls.cpython-38.pyc │ └── wsgi.cpython-38.pyc ├── settings.py ├── urls.py └── wsgi.py
Lista o conteúdo do diretório atual em formato de árvore.
Aqui vemos todos os arquivos dentro do projeto.
Primeira migração para metadados do Django:
$ manage.py migrar
Criação de superusuário do Django:
$ manage.py createsuperuser
Crie um aplicativo:
$ manage.py startapp human_resource
Edite settings.py para adicionar um novo aplicativo:
$ vim my_project/settings.py
# Definição do aplicativoINSTALLED_APPS =[ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django .contrib.staticfiles', # Aplicativos personalizados 'human_resource',]
Um truque legal do Django:você pode usar um diretório models ao invés de um arquivo models.py.
Mas você deve criar um arquivo init dunder (__init__.py) dentro do diretório models.
Vamos lá!
Criação do diretório de modelos dentro do diretório do aplicativo:
$ mkdir human_resource/models
Remova o arquivo models.py:
$ rm -f human_resource/models.py
Criação do modelo:
$ vim human_resource/models/hr.py
from django.db.models import AutoFieldfrom django.db.models import Modelfrom django.db.models import TextFieldclass Person(Model):''' Person Model Namespace:ns_hr Table:tb_person ''' id_ =AutoField(db_column='id_', name='id', primary_key=True,) name =TextField(db_column='name', name='name',) surname =TextField(db_column='sobrenome', name='sobrenome',) def __str__(self):return f'{self.name} {self.surname}' class Meta:db_table ='ns_hr".."tb_person' # 'schema",."object' verbose_name_plural ='Person'
Para aproveitar os benefícios dos esquemas do PostgreSQL, dentro do seu modelo, na classe interna Meta, ao valor do atributo “db_table” você deve colocar um ponto que separe namespace e objeto entre aspas.
'schema"."object'
O objeto pode ser uma tabela ou uma visão, por exemplo…
Dunder init dentro do diretório de modelos para que as migrações entrem em vigor:
vim human_resource/models/__init__.py
de human_resource.models.hr import Person
Isso é necessário para que o diretório de modelos funcione como arquivo models.py.
(Não) Migrações:meu banco de dados, minhas regras!
Nós criamos a estrutura do nosso banco de dados e nenhum ORM deveria fazer isso por nós!
Nós temos o poder!
Nós temos o poder!
Nós estamos no comando!
Nosso banco de dados, nossas regras! 😉
Apenas modele seu banco de dados com suas próprias mãos e faça uma migração falsa do Django.
Porque só nós sabemos como os objetos do banco de dados devem ser criados 😉
Faça migrações para o aplicativo human_resource:
$ manage.py makemigrations human_resource
Migração falsa:
$ manage.py migrar --fake
Vamos verificar a hierarquia de diretórios do aplicativo:
$ tree human_resource/├── admin.py├── apps.py├── __init__.py├── migrations│ ├── 0001_initial.py│ ├── __init__.py__│ └── __pycache─ 0001_initial.cpython-38.pyc│ └── __init__.cpython-38.pyc├── modelos│ ├── hr.py│ ├── __init__.py│ └── __pycache__│8 ├ .pyc│ └── __init__.cpython-38.pyc├── __pycache__│ ├── admin.cpython-38.pyc│ └── __init__.cpython-38.pyc├──tests.py└─├── views. pi
Django Shell (Ipython):
$ manage.py shell
>>> from human_resource.models.hr import Person>>> p =Person(name='Ludwig', surname='van Beethoven')>>> print(p)
Saída:
Ludwig van Beethoven
>>> p.save() # Persistir no banco de dados
Pressione
<Ctrl> + D
sair! Shell de banco de dados (psql):
$ manage.py dbshell
Uma consulta para verificar se os dados foram inseridos pelo Django:
> SELECT id_, nome, sobrenome FROM ns_hr.tb_person;
Saída:
id | nome | sobrenome ----+--------+--------------- 1 | Luís | van Beethoven
Conclusão
PostgreSQL é um RDBMS robusto e poderoso com muitos recursos, incluindo namespaces para seus objetos.
Django é um ótimo framework web que é muito robusto e possui muitos recursos também.
Então, você pode extrair o melhor de ambos para obter melhores resultados e para isso, uma das formas é obter uma melhor organização.
Organizar seus objetos de banco de dados em namespaces de acordo com seus papéis trará benefícios para você 😉