Inicio rápido con Django ORM

django-orm

Como desarrollador web, el uso de bases de datos puede ser una molestia, debe asegurarse de que todas sus queries estén bien estructuradas y que funcionen como se espera, por lo que cuando elige un ORM está en una buena manera de lograrlo, puede escalarlo fácilmente y su código estará más organizado.

El framework web de Django incluye una capa de mapeo relacional de objetos (ORM) predeterminada que se puede usar para interactuar con datos de aplicaciones de varias bases de datos relacionales como SQLite, PostgreSQL y MySQL.

En esta publicación, veremos las queries más comunes que se pueden usar con Django ORM. Si le preocupa la velocidad de su query, porque tiene una gran cantidad de datos o desea profundizar, puede echar un vistazo a estas publicaciones:

Para ejecutar nuestros ejemplos, creemos dos modelos:

from django.db import models
 
 
class Category(models.Model):
    name = models.CharField(max_length=500)
    def __str__(self):
        return self.name
        
class Book(models.Model):
    name = models.CharField(max_length=500)
    author = models.CharField(max_length=200)
    available = models.BooleanField(default=True)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    def __str__(self):
        return self.name

1. Inserte los datos

Cree las migraciones y luego migre:

>>> python manage.py makemigrations
>>> python manage.py migrate

Después de migrar, utilizando el shell puede crear varias categorías y libros:

El primer enfoque usando Django ORM:

>>> Category.objects.create(name="education")
>>> Book.objects.create(name="education", author="author test", category=Category.objects.get(name='education'))

El segundo enfoque usando el modelo de referencia:

>>> category = Category(name="science")
>>> category.save()
>>> book = Book(name="Science book", author="Sciencie Author", category=category)
>>> book.save()

Ambos enfoques son equivalentes

Tenga en cuenta que no establecemos el atributo available, ya que se guardará como el valor predeterminado «True». También en el atributo de category establecemos el valor con el objeto category, que ya se ha guardado en la base de datos.

La categoría foreign key requiere tener un objeto que exista en la base de datos; si inicializa el objeto Categoría () pero no lo guarda, la creación del libro generará un ValueError debido a un objeto relacionado no guardado.

Django también proporciona una manera de crear múltiples objetos a la vez:

>>> Category.objects.bulk_create(
... [Category(name="adventure"),
... Category(name="science"),
... Category(name="education")])
[<Category: adventure>, <Category: science>, <Category: education>]


Bulk_create recibe una lista de objetos no guardados

2. Liste todos los objetos

Para obtener los registros:

>>> qs= Category.objects.all()
>>> qs

La respuesta será algo como esto:

<QuerySet [<Category: science>, <Category: adventure>, <Category: education>, <Category: adventure>]>

A veces necesitamos saber cómo se ve la query. Para ello, utilizamos el atributo query y la función str:

>>> str(query.query)
'SELECT "app1_category"."id", "app1_category"."name" FROM "app1_category"'<br>

3. Actualice los datos

Con la categoría list, vamos a seleccionar la primera y escribir con mayúscula el nombre:

category = Category.objects.first()
>>> category
<Category: science>
>>> category.name = "Science"
>>> category.save()
>>> category.refresh_from_db()
>>> category
<Category: Science>

A veces debe llamar refresh_from_db para actualizar los valores desde la base de datos.

También puede hacer:

>>> Category.objects.filter(name="science").update(name="Science")

4. Seleccione un objeto específico

Si ha establecido el nombre attribute como único, puede usar la función .get:

>>> Category.objects.get(name="education")
<Category: education>

De lo contrario, si hay más de un objeto con ese nombre, elevará el error “MultipleObjectsReturned”.

En caso de que no haya un objeto con ese nombre, un DoesNotExist aparecerá.

Necesitará usar la funciión filter, que devolverá la lista de elementos que coinciden con la query.

>>> Category.objects.filter(name="education")
<QuerySet [<Category: education>]>

5. Field Lookups

Field lookups son como se especifica la carne de una cláusula SQL WHERE. Se especifican como argumentos de palabras clave para los métodos QuerySet filter (), exclude () y get ().

Iexact: La query siguiente buscará el nombre exacto sin tener en cuenta mayúsculas y minúsculas:

>>> c = Category.objects.filter(name__iexact='science')
>>> str(c.query)
>>> 'SELECT "app1_category"."id", "app1_category"."name" FROM "app1_category" WHERE UPPER("app1_category"."name"::text) = UPPER(science)'

Icontains: Hará una query Where de tipo LIKE :

>>> c = Category.objects.filter(name__icontains='education')

>>> str(c.query)
>>> 'SELECT "app1_category"."id", "app1_category"."name" FROM "app1_category" WHERE UPPER("app1_category"."name"::text) LIKE UPPER(%education%)'

Puede encontrar muchas de estas field lookup en el sitio oficial.

6. Queries ‘O’

Recuperemos las categorías que comienzan con «d» o comienzan con «s», usaremos el field lookup startswith, que hará una query de tipo LIKE d%.

La forma común es crear dos conjuntos de queries diferentes y unirse con‘|’:

>>> Category.objects.filter(name__startswith='a') | Category.objects.filter(name__startswith='s')
<QuerySet [<Category: adventure>, <Category: science>]>

La otra manera es usar Q objects, La definición Django dice “Un objeto Q (django.db.models.Q) es un objeto utilizado para encapsular una colección de argumentos de palabras clave. Estos argumentos de palabras clave se especifican como en ‘Field Lookups’”.

>>> Category.objects.filter(Q(name__startswith='a') | Q(name__startswith='s'))<br>

Para ambas opciones, el sql generado será el mismo

7. Queries ‘Y’

Vamos a obtener categorías que comienzan con ‘e’ y terminan con ‘n’, luego tenemos 3 opciones:

  • Crear cada condición con filtro y uniéndola con &:
>>> Category.objects.filter(name__startswith='e') & Category.objects.filter(name__endswith='n')
<QuerySet [<Category: education>]>
  • Usar Q Objects:
>>> Category.objects.filter(Q(name__startswith='e') & Q(name__endswith='n'))<br>
  • Añadir las condiciones dentro de la función filter:
>>> Category.objects.filter(name__startswith='e', name__endswith='n')<br>

Para las 3 opciones obtenemos la misma query:

'SELECT "app1_category"."id", "app1_category"."name" FROM "app1_category" WHERE ("app1_category"."name"::text LIKE %n AND "app1_category"."name"::text LIKE e%)'<br>

8. Query ‘No’

Consigamos todas las categorías cuyas ID son mayores que 2

  • El método Excluderetornará el query que no coincide con la condición:
>>> Category.objects.exclude(id__lt=2)
  • El otro método es usar Q objects con el caracter tilde (~):
>>> Category.objects.filter(~Q(id__lt=2))

9. Union

Union se utiliza para unir el resultado de diferentes conjuntos de queries, cuando la unión es de diferentes modelos, los campos y sus tipos de datos deben coincidir.

>>> q1 = Book.objects.filter(available=True)
>>> q1
>>> <QuerySet [<Book: Science book>]>
>>>  q2 = Book.objects.exclude(available=True)
>>> q2
>>> <QuerySet [<Book: education book>]>
>>> q1.union(q2)
>>> <QuerySet [<Book: education book>, <Book: Science book>]>

10. Juntar Queries

La unión puede ser realizada con el método select_related: Django define esta función como Devuelve un QuerySet que «seguirá» las relaciones foreign-key, seleccionando datos de objetos relacionados adicionales cuando ejecute su query.

>>> Book.objects.select_related('category')<br>

El Query se ve así:

>>> 'SELECT "app1_book"."id", "app1_book"."name", "app1_book"."author", "app1_book"."available", "app1_book"."category_id", "app1_category"."id", "app1_category"."name" FROM "app1_book" INNER JOIN "app1_category" ON ("app1_book"."category_id" = "app1_category"."id")'<br>

Otra forma de unir es con filtro, de la siguiente manera: el nombre de la relación del modelo, seguido de un doble subrayado (__), seguido del nombre del campo:

Book.objects.filter(category__name='science')<br>

11. Agregaciones

A veces necesitamos agregar, contar u obtener datos de un grupo de objetos. Eso se puede hacer con agregaciones:

importe los métodos:

 >>> from django.db.models import Avg, Max, Min, Sum, Count<br>

Veamos algunos de ellos:

Avg: Devuelve el valor medio de la expresión dada.

>>> Category.objects.all().aggregate(Avg('id'))
>>> {'id__avg': Decimal('2.0000000000000000')}

Count: Devuelve el número de objetos que están relacionados a través de la expresión proporcionada.

>>> Category.objects.count()
>>> 3

Use esta función en lugar de len(query), será más eficiente para su lógica como sugiere Django. «Si solo necesita determinar la cantidad de registros en el conjunto (y no necesita los objetos reales), es mucho más eficiente manejar un recuento a nivel de base de datos utilizando el SELECT COUNT(*) de SQL».

Django ORM proporciona una poderosa abstracción de la base de datos, lo que significa un paquete completo de ventajas, podrá escalar más fácilmente, no se preocupará por la inyección de SQL y será fácil de iniciar y crear todo su CRUD.

Estos son algunos de los métodos útiles que nos proporciona Django ORM. Eche un vistazo a la página oficial aquí, los ejemplos anteriores le ayudarán a comenzar con su primera aplicación Django, para hacer las queries que siempre necesitamos para comenzar.