Gestión de Formularios en Django
Con este taller aprenderás a crear y definir nuestros propios formularios utilizando las herramientas que da Django, además...
Aprende de forma práctica a utilizar el ORM de Django para trabajar con bases de datos y realizar todo tipo de queries sobre ellas de una forma sencilla.
¿Quieres interactuar con tu base de datos de manera sencilla?
Con el ORM de Django puedes realizar todo tipo de queries sin complejidad: recuperar información, filtrar y ordenar resultados, usar agregaciones para resumir los datos y mucho más.
En este contenido, encontrarás una guía práctica para empezar a trabajar con bases de datos en Django.
Una de las necesidades de todo proyecto web, es el poder guardar información que luego pueda ser consultada fácilmente, para esto existen las bases de datos.
Existen diferentes tipos de bases de datos que podemos utilizar: SQL, key-value, Documental, Grafos, Orientada a objetos, Columna ancha…
El tipo de nuestra base de datos, dependerá de que datos queremos guardar, y como queremos acceder a ellos más adelante, en función de si necesitamos calcular métricas, información para una red social, baja latencia de acceso a la información.
Debido a los diferentes tipos de bases de datos que existen, y a la popularización de la programación orientada a objetos (OOP), un patrón muy utilizado es el Object Relational Mapping(ORM) es una técnica de software que nos permite interactuar con nuestra base de datos, como si de un objeto más se tratase. De esta forma podemos crear, actualizar o borrar información fácilmente.
Como hemos dicho, este tipo de sistemas son muy utilizados entre los desarrolladores por las ventajas que incluyen:
Pero estas ventajas no vienen sin un coste, ya que esta tecnología aunque son muy populares también vienen con unos tradeoffs o inconvenientes:
Es importante, que los desarrolladores tienen sean conscientes de estas limitaciones, ya que, aunque ofrecen numerosas ventajas, siempre viene con el coste de eliminar parte de la flexibilidad que proporciona el lenguaje en claro de las bases de datos, y algunos ORMs pueden venir con problemas de performance, o comportamientos indeseados, por lo que es necesario conocer la tecnología que se está utilizando.
Muchos de los frameworks más utilizados por los desarrolladores ya incorporan ORMs para facilitar el desarrollo de aplicaciones: Spring - Java, Ruby on Rails - Ruby, Laravel - PHP
Uno de los ORMs más utilizados en el ecosistema Python, es el ORM de Django, no en vano ya que Django es uno de los Frameworks más utilizados entre los amantes de Python, donde destaca la gran comunidad que posee, así como la gran cantidad de libros y cursos de Django a nuestra disposición.
El ORM de Django se focaliza sobre todo en la simplicidad de uso, y la prácticamente nula curva de aprendizaje necesaria para empezar a utilizarlo, además de ser muy versátil. Este ORM funciona sobre todo con Bases de Datos SQL.
El ORM de Django está compuesto de dos componentes principales: Django Models, QuerySets.
Los Django Models son los modelos
para representar las tablas de nuestra base de datos SQL, y modelar así la información.
class Person(models.Model):
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
age = models.IntegerField()
De esta forma cada instancia de nuestro modelo es representa una fila de la tabla, y cada propiedad de la clase una columna.
Una de las partes más deseadas de Django es su capacidad de actualizar la estructura de base de tu base de datos de forma automática, eso lo consigue gracias a los Modelos, ya que es capaz de detectar los cambios en dichos modelos y son utilizados para generar migraciones en Django de forma automática para nuestra DB.
El ORM añade algunas simplicidades, como incluir una propiedad id de forma automática a nuestras tablas, que actúa de primary key, y que podemos utilizar en las consultas de la información, además incluye el alias pk a la primary key de la tabla para que podamos acceder fácilmente.
El otro componente principal son los QuerySets, estos son los objetos que representan una consulta en Django a la Base de Datos, desde la cual se puede recuperar, crear, borrar o actualizar la información de nuestra base de datos.
Estos objetos, tienen varias propiedades:
Para poder crear una nueva QuerySet y consultar la información es muy sencillo, solo tenemos que utilizar nuestros modelos, para decidir a qué información queremos acceder.
A continuación, vamos a revisar cómo podemos hacer varias consultas con el ORM de Django y cules son sus principales métodos, además vamos a ver cómo se traducen estas consultas a su equivalente en SQL.
Django ORM
Person.objects.all()
El método all() recupera todo el contenido que tenemos guardado en nuestro modelo, al hacerlo de forma lazy, podemos aplicar principios de paginación para evitar traer toda la información en memoria. Person.objects.all()[:100]
así traemos solo los 100 primeros resultados de la base de datos.
SQL
SELECT *
FROM person
Django ORM
Person.objects.filter(first_name='Juan', last_name='Hernández')
Django incluye el operador filter(), que nos permite filtrar las filas de nuestra tabla por varios parámetros, sin olvidar que cada parámetro que incluyamos será una sentencia AND adicional.
SQL
SELECT *
FROM person
WHERE first_name = 'Juan' AND last_name = 'Hernández'
Django ORM
Person.objects.filter(first_name__startwith='J')
Los parámetros que utilicemos en el operador filter() permiten que añadamos acciones, como el filtrado por un substring dentro de una cadena de texto, o comprobar si un número es mayor de otro, esto se hace utilizando los dobles: __
.
SQL
SELECT *
FROM person
WHERE first_name like 'J%'
Django ORM
Person.objects.count()
El ORM de Django nos proporciona el método count() que nos permite contar todos los registros de la tabla. Este operador equivale al método COUNT de SQL.
SQL
SELECT COUNT(*)
FROM person
Django ORM
Person.objects.order_by('-age')
El operador (order_by())nos permite ordenar los registros que recuperemos, incluyendo el nombre de la columna como texto, le indicamos sobre que parámetro queremos ordenar, e incluyendo el signo - le decimos que queremos que sea orden descendente, si no ponemos ningún signo será como orden ascendente.
SQL
SELECT *
FROM person
ORDER BY 'AGE' DESC
Django ORM
Person.objects.aggregate(max_age = Max('age'))
El operador aggregate() nos permite hacer operaciones de agregación sobre todos los registros de una tabla, por ejemplo, si queremos sumar las edades de todas las personas, o como en este caso si queremos obtener la edad máxima.
SQL
SELECT MAX(age)
FROM person
Django ORM
Person.objects.annotate(age_count = Count('age')).values('age_count', 'age')
# [{age_count: 10, age: 21}, {age_count:5, age: 22}...]
Django ORM no tiene un operador Group BY como podría ser de esperar, en lugar de eso cuando queremos agrupar información por un parámetro, tenemos que hacer una operación de agregación a nivel de fila con annotate(), en este caso contamos las personas que tienen la misma edad, y con esa operación conseguimos la agrupación.
Al acceder a la información utilizando el ORM, no podemos mapear el resultado a una entidad del modelo, y por eso tenemos que recuperar el diccionario de información en claro, con el operador values().
SQL
SELECT age, COUNT(age) as age_count
FROM person
GROUP BY age
Django ORM
Person.objects.create(first_name='Antonio', last_name='Hernandez', age=29)
La creación de nueva información en nuestros modelos se hace a través del operador create().
SQL
INSERT INTO person (first_name, last_name, age)
VALUES ('Antonio', 'Hernandez', 29);
Django ORM
Person.objects.filter(first_name='Antonio').update(first_name='Tony')
La actualización de información se hace con el operador update(), donde solo tenemos que especificar la información que queremos actualizar.
Cómo comentábamos podemos extender nuestras QuerySets con varios operadores, nuestro operador filter, esto nos permite concatenar varios operadores. Cuidado porque el operador update no devuelve otro QuerySet.
Una forma alternativa de actualizar un registro de nuestro modelo, es una vez tenemos nuestra instancia person, utilizar el método save(), después de modificarla.
SQL
UPDATE person
SET first_name = 'Tony'
WHERE first_name = 'Antonio'
Django ORM
Person.objects.filter(age__gt=30).delete()
De la misma forma que tenemos los operadores update() y create() para insertar y actualizar información en nuestros modelos, tenemos el operador delete() para borrar uno o varios registros en nuestros modelos.
SQL
DELETE FROM person
WHERE age > 30
Una de las virtudes de las bases de datos SQL, es su capacidad de relacionar información, ya que así es como podemos modelar la información en nuestra base de datos. Estas relaciones se hacen a través de lo que llamamos llaves foráneas.
Estas relaciones nos ayudan a separar cierta información que consideramos independiente en diferentes tablas, y aun así utilizarla para expandir la información que tenemos en nuestras tablas. Por ejemplo, en la imagen de arriba, tenemos la información de nuestros clientes, separada de la información de los pedidos que han hecho.
Pero aun así gracias a las relaciones podemos acceder a la información de los pedidos de nuestros clientes cuando consideremos oportuno y de forma muy sencilla.
La creación de relaciones y claves foráneas en Django es mediante las clases ForeignKey, donde solo hay que especificar el modelo al que queremos referenciar, para crear la relación.
class Customer(models.Model):
name = models.CharField(max_length=50)
age = models.IntegerField()
country = models.CharField(max_length=50)
class Order(models.Model):
date = models.DateTime()
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
amount = models.IntegerField()
Django ORM
order = Order.objects.get(pk=1)
order.customer.name # Nombre del customer
Al recuperar nuestra fila order con id=1, ya somos capaces de acceder a la información del cliente relacionado con dicho order, este acceso lo hace Django de forma completamente transparente a nosotros.
Además, comentar que como hemos dicho anteriormente, las QuerySets son lazy, eso provoca que realmente Django haga 2 queries, una primera para recuperar el order con id=1 (SELECT * FROM order WHERE id =1
), y una adicional para acceder a la información del customer, que es la que vemos abajo.
SQL
SELECT order.*, customer.name as name
FROM order
LEFT JOIN customer ON order.customer_id = customer.id
Django ORM
Order.objects.filter(customer__age__gt = 30)
Una de las grandes ventajas de utilizar relaciones es poder acceder a la información de diferentes tablas cuando nos sea necesario, esto también aplicar cuando estamos buscando la información, Django nos permite hacer esto fácilmente utilizando la sintaxis de doble _, además como vemos en el ejemplo podemos concatenar el acceso a la información de nuestra relación con un operador de búsqueda como el __gt
.
SQL
SELECT *
FROM order
LEFT JOIN customer on order.customer_id = customer.id
WHERE customer.age > 30
Django ORM
customer = Person.objects.get(pk=1)
orders = person.order_set.all() # Accediendo a todos los pedidos de un cliente
Algo muy destacable del ORM de Django es su clara sintaxis que facilita mucho la curva de aprendizaje, como podemos ver en este caso, cuando necesitamos seguir una relación a la inversa, es decir en lugar del modelo acceder desde el hijo al padre, es desde el padre al hijo. En ese caso solo es necesario una vez tengamos la instancia del padre, llamar a la propiedad “nombre del hijo”_set
, y ya podremos utilizar cualquier operador visto para conseguir la información que necesitemos, además podemos customizar este nombre utilizando la propiedad related_name().
SQL
SELECT *
FROM order
WHERE order.customer_id = 1
El poder hacer búsquedas sobre la información que tenemos almacenadas es una de las grandes ventajas que existen en las bases de datos SQL, los ORMs pueden sernos tremendamente útiles siempre que sepamos cómo utilizarlos.
Django nos provee de un ORM para comunicarnos con nuestra base de datos y hacer queries de forma muy sencilla a la par que muy versátil y que es capaz de adaptarse a nuestras necesidades, haciendo que la gestión de migraciones, relaciones y buenas prácticas sea muy sencilla.
También te puede interesar
Con este taller aprenderás a crear y definir nuestros propios formularios utilizando las herramientas que da Django, además...
Aprende con nuestro profesores los conceptos teóricos de arquitectura hexagonal, y cómo llevarla a la práctica en tus...