ORM en Django
Tags: django, python, orm, webdev
Published: 2021-11-12 20:47:08

Una vez entendiendo la manera de trabajar de django con respecto a los templates, views y urls, nos vemos en la necesidad de entender el trabajo que involucra la parte de los datos, la capa del modelado, y en django, se trabaja bajo la lógica del ORM.

Si aún no comprendes que es ORM en si, te aconsejaría leer  [este artículo (click acá)](https://codigofacilito.com/articulos/orm-explicacion) antes de seguir con esta lectura.

Para entender como se trabajan las ORM en Django crearemos un ejemplo con tres clases: Author, Book y Reader.

En nuestro archivo models.py de nuestra app books, tenemos el siguiente contenido:
```python
from django.db import models

class Author(models.Model):
    first_name = models.CharField(verbose_name="Nombres", max_length=50)
    last_name = models.CharField(verbose_name="Apellidos", max_length=50)
    def __str__(self):
        return self.first_name + " " + self.last_name

class Book(models.Model):
    name = models.CharField(verbose_name="Nombre del libro", max_length=50)
    author = models.ForeignKey(Author, related_name="books",verbose_name="Autor", on_delete=models.CASCADE)
    price = models.FloatField(verbose_name="Precio")
    preview = models.FileField(upload_to="books/", verbose_name="Adjunto del libro")

    def __str__(self):
        return self.name

class Reader(models.Model):
    first_name = models.CharField(verbose_name="Nombres", max_length=50)
    last_name = models.CharField(verbose_name="Apellidos", max_length=50)
    readed_books = models.ManyToManyField(Book, related_name="readers")

    def __str__(self):
        return self.first_name + " " + self.last_name
```

En este punto, tenemos varias cosas que ya manejamos, pero procederé para refrescar:

- *models.CharField, models.FloatField, models.FileField* : funciones que se encargan de asignar un tipo de dato a un atributo de la clase (que se convertirá en una columna en la base de datos), la mayoría de ellos reciben parámetros como verbose_name, max_length, upload_to, que se encargan de cambiar las características de este atributo.
- *models.ForeignKey, models.ManyToMany*: en ORM existen varias maneras de relacionar entre las clases: 1 a 1, 1 a muchos y de muchos a muchos, cuando se ocupan estas funciones solo escribimos la relación que tendrán, comúnmente se agrega un related_name, que será clave para las llamadas en ambos sentido.

Como la base de datos estaba con datos, se limpió y se hizo make migrations y migrate.

Una vez hecho esto, procederemos a trabajar con las ORM, todo esto lo haremos en la shell de django:

## Creación de objetos.

Tenemos dos maneras de crear objetos, la primera manera, se crea el objeto y luego se guarda en la base de datos, y la otra manera es crear el objeto en la base de datos directamente.

```bash
>>> from books.models import Author
>>> new_author = Author(first_name="Axel",last_name="García")
>>> new_author.save() # Primera manera
>>> Author.objects.create(first_name="Fulano",last_name="Del Rosario") # segunda manera
<Author: Fulano Del Rosario>
```
Para la creación de los primeros libros, usaremos la variable new_author que actualmente guarda el autor Axel García.

```bash
>>> from books.models import Book
>>> new_book = Book(name="Primero", author=new_author, price=120, preview="google.com")
>>> new_book.save()
>>> new_book2 = Book(name="Segundo", author=new_author, price=120, preview="google.com")
>>> new_book2.save()
```
Y por último, agregaremos los primeros lectores.
```bash
>>> from books.models import Reader
>>> new_reader = Reader(first_name="Santiago", last_name="Matamoros")
>>> new_reader.save()
```
En el caso de los libros, rellenar el autor del libro fue fácil porque solo debes de pasar el objeto, en caso de las relaciones de muchos a muchos, debes tratarlos como una colección, para este ejemplo, se agregaran como "readed_books", los dos libros creados, de la siguiente manera: 
```bash
>>> new_reader.readed_books.add(new_book)
>>> new_reader.readed_books.add(new_book2)
```
Para confirmar que esto se realice exitosamente, podemos inspeccionar lo que tenemos en readed_books, pero, como dije, debemos de tratarlo como una colección:
```bash
>>> new_reader.readed_books.all()
<QuerySet [<Book: Primero>, <Book: Segundo>]>

```
De esta manera podemos trabajar las relacionas con las ORM, este ejemplo es algo rápido, así que cualquier comentario para mejorarlo o agregar más cosas que sean necesarias, estoy pendiente.

Fuentes: 
- https://docs.djangoproject.com/en/3.2/topics/db/models/
Código fuente:
- https://github.com/pacisauctor/biblio