Pythone especialmente o Django, são essenciais para construir aplicações mais eficientes, com menos código, e conectados a um banco de dados altamente escalonável. Estou aqui para falar com você sobre reduzir o atrito diário que vem com a construção e suporte de aplicações modernas usando SQL e Python para abstrair a complexidade e tornar nossos trabalhos e nossas vidas um pouco mais fáceis.
Sem entrar nas ervas daninhas, podemos assumir:
- SQL é otimizado para bancos de dados SQL
- Python não está otimizado para bancos de dados SQL
Este exercício suporta diretamente o ebook Understanding Databases e minha nova série educativa Linode LIVE! usando Python e ferramentas Pythonic para executar comandos em SQL bruto sem a necessidade de realmente escrever SQL. Estou usando a modelagem de dados do Django, mas a sintaxe é muito similar ao pacote SQLAlchemy em Python.
Vamos começar!
Aqui está um exemplo de um modelo de dados Django:
class BlogArticle(models.Model):
user = models.ForeignKey(User, default=1, on_delete=models.SET_DEFAULT)
title = models.CharField(max_length=120)
slug = models.SlugField(blank=True, null=True)
content = models.TextField(blank=True, null=True)
publish_timestamp = models.DateTimeField(
auto_now_add=False,
auto_now=False,
blank=True,
null=True,
)
Vamos assumir que este modelo vive em um aplicativo Django chamado Articles
(As aplicações Django são essencialmente componentes que compõem a totalidade de um projeto Django).
Portanto, agora temos dois nomes para trabalhar:
Articles
(nome do aplicativo)BlogArticle
(nome do modelo)
Em combinação, estes se traduzem no nome da Tabela SQL:
articles_blog_article
Django faz esta magia para nós.
Se estivéssemos usando a casca do MySQL, veríamos:
mysql> SHOW TABLES;
+------------------------------+
| Tables_in_cfe_django_blog_db |
+------------------------------+
| articles_blog_article |
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+------------------------------+
11 rows in set (0.01 sec)
Agora vamos ver as colunas em nosso modelo Django:
mysql> DESCRIBE articles_blog_article;
+------------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+--------------+------+-----+---------+----------------+
| id | bigint | NO | PRI | NULL | auto_increment |
| title | varchar(120) | NO | | NULL | |
| slug | varchar(50) | YES | MUL | NULL | |
| content | longtext | YES | | NULL | |
| publish_timestamp | datetime(6) | YES | | NULL | |
| user_id | int | NO | MUL | NULL | |
+------------------------+--------------+------+-----+---------+----------------+
12 rows in set (0.00 sec)
Além de escrever uma configuração básica, Django fez todo o trabalho de SQL para nós neste banco de dados MySQL, e neste ponto, Django não fez nada muito impressionante. Na verdade, a maior parte deste exercício não foi projetado para destacar Django ou Python como um substituto do SQL, mas para lembrar o fato de que as abstrações funcionam.
A Ascensão de Python e o Custo do Atrito
Vamos falar sobre o caminho de menor resistência e por que acredito que Python é uma das melhores maneiras de alavancar o SQL.
É muito fácil de escrever, ler, correr e enviar Python. Mude "Python" para quase qualquer outro paradigma de programação e é quase impossível fazer a mesma afirmação. O JavaScripttambém é um concorrente, mas também é consistentemente confuso para Java. Entendo que estas são generalizações, e nem sempre são verdadeiras, mas são questões comuns que surgem ao desenvolver seu aplicativo.
Acredito que estas generalizações tendem a ser verdadeiras devido à sintaxe inglesa de fazer as coisas em Python.
Vamos comparar uma declaração SQL com uma declaração Python e Django:
- SQL:
SELECT * from articles_blog_article;
- Python e Django:
items = BlogArticle.objects.all()
Ambas as declarações produzem exatamente os mesmos dados. A declaração Python , entretanto, retorna uma lista de Python objetos (items
) que quase qualquer desenvolvedor Python em toda uma gama de experiências pode utilizar. Os resultados do SQL bruto precisariam ser convertidos antes de serem usados em um aplicativo Python .
Descrições de campo
Se olharmos mais de perto esta descrição de campo SQL:
+------------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------------+--------------+------+-----+---------+----------------+
| title | varchar(120) | NO | | NULL | |
+------------------------+--------------+------+-----+---------+----------------+
Versus esta descrição de campo Django:
title = models.CharField(max_length=120)
- Qual deles tem mais atrito?
- Qual deles é mais fácil de entender o que está acontecendo?
O que fornece apenas informações suficientes?
Se você não fosse um codificador e serrasse varchar(120)
O que você acha disso? Tenho certeza de que você poderia ao menos adivinhar o que max_length=120 means
. O legal é que eles significam exatamente a mesma coisa: limitar este campo a 120 caracteres ou menos.
Adição de dados ao banco de dados
Com Django:
BlogArticle.objects.create(
title="Hello World",
content="Coming Soon",
slug="hello-world",
publish_timestamp=None,
)
Com SQL:
INSERT INTO `articles_blog_article` (`user_id`, `title`, `slug`, `content`, `publish_timestamp`)
VALUES (1, 'Hello World', 'hello-world', 'Coming Soon', NULL);
Quando se trata de simplicidade e clareza, eu acho que o vencedor acima é definitivamente Django e Python. title = "Hello World"
é mais fácil do que descobrir o que está acontecendo com o valor equivalente da coluna (campo) em SQL. Não se engane, a forma como isto é escrito em SQL é muito eficaz quando se sabe o que se está fazendo.
Adicionando Múltiplas Linhas
com Django:
items = [
BlogArticle(title='Hello Again 0', slug='hello-again-0', content="Coming Soon"),
BlogArticle(title='Hello Again 1', slug='hello-again-1', content="Coming Soon"),
BlogArticle(title='Hello Again 2', slug='hello-again-2', content="Coming Soon"),
BlogArticle(title='Hello Again 3', slug='hello-again-3', content="Coming Soon"),
BlogArticle(title='Hello Again 4', slug='hello-again-4', content="Coming Soon"),
]
BlogArticle.objects.bulk_create(items)
Com SQL:
INSERT INTO `articles_blog_article` (`user_id`, `title`, `slug`, `content`, `publish_timestamp`)
VALUES (1, 'Hello Again 0', 'hello-again-0', 'Coming Soon', NULL),
(1, 'Hello Again 1', 'hello-again-1', 'Coming Soon', NULL),
(1, 'Hello Again 2', 'hello-again-2', 'Coming Soon', NULL),
(1, 'Hello Again 3', 'hello-again-3', 'Coming Soon', NULL),
(1, 'Hello Again 4', 'hello-again-4', 'Coming Soon', NULL);
Novamente, o código Python é mais legível, enquanto o código SQL dá mais informações sobre os dados reais. E, mais uma vez, Python está escrevendo este código SQL para nós usando o código Django acima. Bastante legal, não?
A razão pela qual eu mergulhei nesta comparação lado a lado não é para escolher, que é a melhor maneira de alavancar bancos de dados SQL, mas para destacar a capacidade de Pythonde ajudar a reduzir a sobrecarga de aprendizagem para escrever SQL bruto diretamente.
Há vários pacotes Python que eles essencialmente escrevem o SQL bruto para você, aqui estão alguns deles:
- Django
- Pandas
- SQLAlchemy
- Polars
- Dask
- Vaex
- PythonMódulo CSV incorporado
- Tartaruga ORM
- Pônei ORM
- SQLObject
Django Faz a Elevação Pesada
Os pacotes de mapeamento objeto-relacional (comumente chamados de ORMs) são o molho secreto de como Python pode alavancar bancos de dados SQL. Eu penso em um ORM como um intermediário que ajuda a mover dados em qualquer sintaxe nativa de qualquer linguagem de programação.
No início deste exercício, começamos a ver como isso se traduzia em Django, mas vamos agora expandir isso.
Supondo que temos dados em nosso banco de dados, podemos escrever um comando como este:
my_post = BlogArticle.objects.first()
Esta declaração irá consultar nosso banco de dados, extrair os dados, carregá-los em uma instância de um Python Class
e, em seguida, atribuí-la à variável my_post
.
A partir daqui, podemos agora fazer algo assim:
# using a django-managed python shell
# via python manage.py shell
>>> print(my_post.title)
Hello World
Neste caso, utilizamos a notação de pontos para acessar o title
campo que foi declarado no BlogPost
Modelo Django da seção anterior. Este campo corresponde a uma coluna em nossa tabela de banco de dados SQL articles_blog_article
.
Graças à ORM, podemos fazer isso:
>>> my_post.title = "some other title"
Dentro deste exemplo de sessão shell Python , o my_post.title
agora sempre ser "some other title"
. O banco de dados SQL subjacente, no entanto, ainda reconhece esses mesmos dados que Hello World
. O banco de dados manterá os dados originais até que Python finalmente se comprometa (aka .save()
) estes dados mudam para o banco de dados. Se Python nunca comprometer estes dados, eles nunca serão atualizados no banco de dados, o que faz parte da magia da ORM. Nós podemos uso e mudar os dados sem afetar os dados efetivamente armazenados. Quando queremos mudar o que está realmente acontecendo no banco de dados, executamos:
>>> my_post.title = "some other title again"
>>> my_post.save()
Após a execução .save()
nosso banco de dados, para esta linha em particular, atualizará o título da coluna para corresponder exatamente ao que está escrito como uma string Python acima. Não esqueça que o .save()
é especificamente para fazer compromissos com o banco de dados nos modelos Django. .save()
não significa realmente nada para um Python Class
sem herdar primeiro um formulário Django Model Class.
Construção com Django, MySQL, e Linode
Este é um dos muitos exemplos de como Django faz o trabalho pesado para você. Se você estiver interessado em uma abordagem moderna para implantar aplicações Django no Linode junto com um banco de dados MySQL gerenciado, GitHub Actions for CI/CD, Terraform e Ansible, confira o seguinte conteúdo agora disponível no Linode:
- Assista nossa série de tutoriais em vídeo sobre o Linode LIVE!
- Baixe os Bancos de Dados de Entendimento: Edição ampliada do Ebook
Para ajudar você a começar, o Código para Empresários GitHub tem um repositório de código que acompanha cada etapa da série. Boa sorte, e não deixe de me informar como as coisas estão indo através do Twitter @JustinMitchel.
Comentários