You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/services/post/files/django-optimizations.en-us.md
+26-26Lines changed: 26 additions & 26 deletions
Original file line number
Diff line number
Diff line change
@@ -1,18 +1,18 @@
1
-
# Ways to optimize queries in Django 🐍🚀
1
+
##Ways to optimize queries in Django 🐍🚀
2
2
3
3
We can make our operations more performant using Django's own methods, generally request delays are consequence from multiple JOINS performed inside queries, result from model's relationships.
4
4
5
-
## 1. Using `prefetch_related()` and `select_related()`
5
+
###1. Using `prefetch_related()` and `select_related()`
6
6
7
7
When we define the ***queryset*** of a ***view*** we can perform ***JOINS*** in advance within it. Thus, we reduce the number of operations that will be realized later.
8
8
9
9
**Example:** Within the ***serializer*** used by ***view*** we need data from some entity related to the model, to fill in a field for example. So for each instance that will be serialized, a set of operations will be performed to bring this data. When performing these operations in ***view*** when defining the ***queryset***, all operations will be done in a single shot, carrying all needed data to serializer.
10
10
11
-
### `select_related()`: Used for 1-to-1 `OneToOneField` or `ForeignKey` relationships.
11
+
**`select_related()`**: Used for 1-to-1 `OneToOneField` or `ForeignKey` relationships.
12
12
13
-
### `prefetch_related()`: Using for relationships where we will have several objects, such as `ManyToManyField` or reverse `ForeignKey` accesses.
13
+
**`prefetch_related()`**: Using for relationships where we will have several objects, such as `ManyToManyField` or reverse `ForeignKey` accesses.
14
14
15
-
### Example:
15
+
**Example:**
16
16
17
17
```python
18
18
# models.py
@@ -28,7 +28,7 @@ class Employee(models.Model):
28
28
company = models.ForeignKey(Company, on_delete=models.PROTECT, blank=True, null=True)
29
29
```
30
30
31
-
### In the `Employee` entity serializer we look for the *name* of `Company` through the *FK*, each time this *serializer* receives an instance to *serialize*, it will do a *JOIN* with ` Company` to fetch the data.
31
+
In the `Employee` entity serializer we look for the *name* of `Company` through the *FK*, each time this *serializer* receives an instance to *serialize*, it will do a *JOIN* with ` Company` to fetch the data.
32
32
33
33
```python
34
34
# serializers.py
@@ -45,7 +45,7 @@ class EmployeeSerializer(serializers.ModelSerializer):
45
45
]
46
46
```
47
47
48
-
### In the `Employee` entity *view* we use `select_related()` passing the *FK* field to `Company`, thus an *INNER JOIN* is performed in the *queryset*, without the need to be performed individually in the serializer.
48
+
In the `Employee` entity *view* we use `select_related()` passing the *FK* field to `Company`, thus an *INNER JOIN* is performed in the *queryset*, without the need to be performed individually in the serializer.
49
49
50
50
```python
51
51
# views.py
@@ -54,15 +54,15 @@ class EmployeeViewSet(ModelViewSet):
**In the `Order` entity we are performing the *JOIN* with its foreign keys `['contract', 'interest', 'company', 'owner']`, and a `prefetch_related()` with several instances accessed through the `'__'` lookups of Django fields.**
81
+
In the `Order` entity we are performing the *JOIN* with its foreign keys `['contract', 'interest', 'company', 'owner']`, and a `prefetch_related()` with several instances accessed through the `'__'` lookups of Django fields.
82
82
83
-
## 2. Avoiding loops and using methods like `aggregate()` and `update()`
83
+
###2. Avoiding loops and using methods like `aggregate()` and `update()`
84
84
85
85
We can avoid building loops using some alternatives, depending on the context.
86
86
87
-
### `aggregate()`
87
+
**`aggregate()`**
88
88
89
-
**Inserts a field into the *queryset* and finally returns a dictionary `(dict)`.**
89
+
Inserts a field into the *queryset* and finally returns a dictionary `(dict)`.
90
90
91
-
### Example:
91
+
**Example:**
92
92
93
93
- Using `loop`
94
94
@@ -110,9 +110,9 @@ We can avoid building loops using some alternatives, depending on the context.
110
110
total_price = items.get('total_price', 0)
111
111
```
112
112
113
-
### Both ways are iterating over the objects from Item entity and adding their price field, however using `aggregate` we are performing a more performant operation due to several Django reasons and also database optimizations.
113
+
Both ways are iterating over the objects from Item entity and adding their price field, however using `aggregate` we are performing a more performant operation due to several Django reasons and also database optimizations.
**Here we are filtering a set of objects, then we are aggregating in the new field `total_price` the values from `price` field that is present in the primary key object of the `item` field. We perform aggregation with the `Sum()` operator and the `F()` operator, `F()` converts a field to be used in operations.**
135
+
Here we are filtering a set of objects, then we are aggregating in the new field `total_price` the values from `price` field that is present in the primary key object of the `item` field. We perform aggregation with the `Sum()` operator and the `F()` operator, `F()` converts a field to be used in operations.
136
136
137
-
### `update()`
137
+
**`update()`**
138
138
139
-
### In the same way that `aggregate` is more performant than loops, making some changes in objects using `update()` becomes more performant than changing directly from object's fields.
139
+
In the same way that `aggregate` is more performant than loops, making some changes in objects using `update()` becomes more performant than changing directly from object's fields.
### Both ways are updating the item's `name` field with `pk=15`, but the second becomes more performant for bulk updates or when we don't need to directly access the field. The first mode is more necessary when we need to perform some calc or logic.
171
+
Both ways are updating the item's `name` field with `pk=15`, but the second becomes more performant for bulk updates or when we don't need to directly access the field. The first mode is more necessary when we need to perform some calc or logic.
172
172
173
-
## 3. Creating a `serializer` for each specific context
173
+
###3. Creating a `serializer` for each specific context
174
174
175
-
**If a `view` will not use all the fields from a model or you need to *serialize* an object within another `serializer`, and these fields require some effort to be *serialized*, it is worth creating a `serializer ` model-specific ` view `, using only what you will need.**
175
+
If a `view` will not use all the fields from a model or you need to *serialize* an object within another `serializer`, and these fields require some effort to be *serialized*, it is worth creating a `serializer ` model-specific ` view `, using only what you will need.
@@ -223,4 +223,4 @@ class ComplexProductSerializer(serializers.ModelSerializer):
223
223
]
224
224
```
225
225
226
-
### `Product` contains several serializers with clearly defined objectives, it is noticeable that the last `(ComplexProductSerializer)` generates a high volume of data, making it less performant, so in a situation where I only need the basics, I can use an existing one or create a new one with the necessary fields.
226
+
`Product` contains several serializers with clearly defined objectives, it is noticeable that the last `(ComplexProductSerializer)` generates a high volume of data, making it less performant, so in a situation where I only need the basics, I can use an existing one or create a new one with the necessary fields.
0 commit comments