Ir al contenido principal
BlogBases de datosCómo Django hace el trabajo pesado para SQL

Cómo Django hace el trabajo pesado para SQL

Cómo Django hace el trabajo pesado - Blog Header

Pythony especialmente Django, son esenciales para construir aplicaciones más eficientes, con menos código y conectadas a una base de datos altamente escalable. Estoy aquí para hablarte sobre cómo reducir la fricción diaria que supone construir y dar soporte a aplicaciones modernas usando SQL y Python para abstraer la complejidad y hacer nuestro trabajo y nuestras vidas un poco más fáciles.

Sin entrar en detalles, podemos suponer:

  • SQL está optimizado para bases de datos SQL
  • Python no está optimizado para bases de datos SQL

Este ejercicio apoya directamente el ebook Understanding Databases y mi nueva serie educativaLinode LIVE! usando Python y herramientas Pythonic para ejecutar comandos en SQL crudo sin necesidad de escribir realmente SQL. Estoy usando el modelado de datos de Django, pero la sintaxis es muy similar al paquete SQLAlchemy en Python.

Empecemos.
Aquí
hay un ejemplo de un modelo de datos 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,
    )

Supongamos que este modelo vive en una aplicación Django llamada Articles (Las aplicaciones Django son esencialmente componentes que conforman la totalidad de un proyecto Django).

Así que ahora tenemos dos nombres con los que trabajar:

  • Articles (nombre de la aplicación)
  • BlogArticle (nombre del modelo)

En combinación, se traducen en el nombre de la tabla SQL:

articles_blog_article

Django hace esta magia por nosotros.

Si estuviéramos usando la shell de MySQL lo 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)

Ahora echemos un vistazo a las columnas de nuestro 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)

Aparte de escribir una configuración básica, Django hizo todo el trabajo SQL por nosotros en esta base de datos MySQL.En este punto, Django no ha hecho nada muy impresionante. De hecho, la mayor parte de este ejercicio no está diseñado para destacar Django o Python como un reemplazo de SQL, sino para recordarte el hecho de que las abstracciones funcionan.

El auge de Python y el coste de la fricción

Hablemos del camino de menor resistencia y de por qué creo que Python es una de las mejores formas de aprovechar SQL.

Es muy fácil escribir, leer, ejecutar Y enviar Python. Cambie "Python" por casi cualquier otro paradigma de programación y será casi imposible hacer la misma afirmación. JavaScripttambién es un contendiente, pero también se confunde constantemente con Java. Entiendo que estas son generalizaciones, y no siempre son ciertas, pero son problemas comunes que surgen al desarrollar su aplicación.

Creo que estas generalizaciones tienden a ser ciertas debido a la sintaxis inglesa de Pythonpara hacer las cosas.

Comparemos una sentencia SQL con una sentencia Python y Django:

  • SQL: SELECT * from articles_blog_article;
  • Python y Django: items = BlogArticle.objects.all()

Ambas sentencias devuelven exactamente los mismos datos. La sentencia Python , sin embargo, devuelve una lista de objetos Python (items) que casi cualquier desarrollador de Python con distintos niveles de experiencia puede utilizar. Sería necesario convertir los resultados SQL sin procesar antes de utilizarlos en una aplicación de Python .

Descripciones de campo
Si observamos con más detenimiento esta descripción de campo SQL:

+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| title                  | varchar(120) | NO   |     | NULL    |                |
+------------------------+--------------+------+-----+---------+----------------+

Frente a esta descripción de campo de Django:

title = models.CharField(max_length=120)

  • ¿Cuál tiene más fricción?
  • ¿Cuál es más fácil de entender?

¿Qué proporciona información suficiente?

Si usted no fuera un codificador y viera varchar(120)¿Qué te parece? Estoy bastante seguro de que al menos podrías adivinar lo que max_length=120 means. Lo bueno es que significan exactamente lo mismo: limite este campo a 120 caracteres o menos.

Añadir datos a la base de datos

Con Django:

BlogArticle.objects.create(
    title="Hello World",
    content="Coming Soon",
    slug="hello-world",
    publish_timestamp=None,
)

Con SQL:

INSERT INTO `articles_blog_article` (`user_id`, `title`, `slug`, `content`, `publish_timestamp`) 
VALUES (1, 'Hello World', 'hello-world', 'Coming Soon', NULL);

Cuando se trata de simplicidad y claridad, creo que el ganador es definitivamente Django y Python. title = "Hello World" es más fácil que averiguar qué pasa con el valor equivalente de la columna (campo) en SQL. No te equivoques, la forma en que esto está escrito en SQL es muy eficaz cuando sabes lo que estás haciendo.

Añadir múltiples líneas
con 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)

Con 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);

De nuevo, el código Python es más legible mientras que el código SQL da más información sobre los datos reales. Y, una vez más, Python está escribiendo este código SQL para nosotros usando el código Django anterior. Muy bonito, ¿eh?

La razón por la que he realizado esta comparación no es para elegir cuál es la mejor forma de aprovechar las bases de datos SQL, sino para destacar la capacidad de Pythonpara ayudar a reducir la sobrecarga de aprender a escribir SQL directamente.

Hay varios paquetes Python que esencialmente escriben el SQL en bruto para usted, aquí están algunos de ellos:

  • Django
  • Pandas
  • SQLAlchemy
  • Polares
  • Dask
  • Vaex
  • PythonMódulo CSV integrado
  • Tortuga ORM
  • Pony ORM
  • SQLObject

Django hace el trabajo pesado
Los paquetes de mapeo objeto-relacional (comúnmente conocidos como ORM) son la salsa secreta para que Python pueda aprovechar las bases de datos SQL. En mi opinión, un ORM es un intermediario que ayuda a mover datos en la sintaxis nativa de cualquier lenguaje de programación.

Anteriormente en este ejercicio, empezamos a ver cómo esto se tradujo a Django, pero vamos a ampliar en eso ahora.

Supongamos que tenemos datos en nuestra base de datos, podemos escribir un comando como este:

my_post = BlogArticle.objects.first()
Esta sentencia consultará nuestra base de datos, extraerá los datos y los cargará en una instancia de un archivo Python Classy asignarlo a la variable my_post.

A partir de aquí, podemos hacer algo como esto:

# using a django-managed python shell
# via python manage.py shell
>>> print(my_post.title)
Hello World

En este caso, utilizamos la notación por puntos para acceder a la función title declarado en el campo BlogPost Django de la sección anterior. Este campo corresponde a una columna de nuestra tabla de base de datos SQL articles_blog_article.

Gracias al ORM, podemos hacerlo:

>>> my_post.title = "some other title"

En este ejemplo de sesión de shell Python , la función my_post.title ahora siempre sea "some other title". Sin embargo, la base de datos SQL subyacente sigue reconociendo estos mismos datos como Hello World. La base de datos conservará los datos originales hasta que Python haga finalmente el commit (también conocido como .save()) este cambio de datos a la base de datos. Si Python nunca consigna estos datos, nunca se actualizarán en la base de datos. Esto forma parte de la magia del ORM. Podemos utilice y cambiar los datos sin afectar a los datos almacenados reales. Cuando queremos cambiar lo que realmente está sucediendo en la base de datos ejecutamos:

>>> my_post.title = "some other title again"
>>> my_post.save()

Después de correr .save() nuestra base de datos, para esta fila en particular, actualizará el título de la columna para que coincida exactamente con lo que está escrito como una cadena Python más arriba. No olvide que el .save() es específico para hacer commits a la base de datos en modelos Django. .save() en realidad no significa nada para un Python Class sin que primero herede un formulario Django Model Class.

Construir con Django, MySQL y Linode

Este es uno de los muchos ejemplos de cómo Django hace el trabajo pesado por ti. Si estás interesado en un enfoque moderno para desplegar aplicaciones Django en Linode junto con una base de datos MySQL gestionada, GitHub Actions para CI/CD, Terraform, y Ansible, echa un vistazo a los siguientes contenidos ahora disponibles en Linode:

Para ayudarte a empezar, el GitHub de Coding for Entrepreneurs tiene un repositorio de código que va con cada paso de la serie. Buena suerte, y asegúrese de hacerme saber cómo van las cosas a través de Twitter @JustinMitchel.


Comentarios

Dejar una respuesta

Su dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *.