Django ORM є потужним інструментом, але навіть досвідчені розробники можуть не використовувати його на повну силу. У цьому пості я поділюсь деякими маловідомими порадами та трюками для створення класів моделей Django, які допоможуть спростити ваш код, покращити продуктивність і зробити вашу роботу як розробника легшою.
1. Використовуйте опції Meta
для магії
Клас Meta
в моделях Django — це не просто місце для визначення verbose назв. Він має численні можливості, які можуть значно зменшити кількість шаблонного коду. Ось кілька важливих моментів:
A. За замовчуванням сортування
Замість того, щоб вручну сортувати querysets у кожному вигляді, визначте сортування за замовчуванням у вашій моделі:
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=10, decimal_places=2)
class Meta:
ordering = ['-price'] # Продукти будуть відсортовані за ціною у спадаючому порядку
B. Кастомні імена таблиць
Якщо вам потрібно дотримуватись специфічних конвенцій бази даних, ви можете змінити ім'я таблиці прямо в моделі:
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255)
class Meta:
db_table = 'custom_product_table'
2. Використовуйте __str__()
ефективно
Це поширена практика — визначити метод __str__()
для моделі, але чому б не зробити більше, ніж просто вивести ім'я? Ви можете зробити відлагодження та ведення логів простішими, включивши додатковий контекст:
from django.db import models
class Order(models.Model):
order_id = models.CharField(max_length=100)
customer_name = models.CharField(max_length=255)
def __str__(self):
return f"Order {self.order_id} by {self.customer_name}"
Таким чином, ваші об'єкти надаватимуть змістовні представлення під час розробки та тестування.
3. Абстрактні базові моделі для спільних полів
Замість того, щоб повторювати загальні поля, такі як created_at
та updated_at
у кожній моделі, створіть абстрактну базову модель:
from django.db import models
class TimestampedModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Product(TimestampedModel):
name = models.CharField(max_length=255)
Тепер кожна модель, що наслідує TimestampedModel
, автоматично матиме поля created_at
та updated_at
.
4. Використовуйте choices
для значень полів
Для полів з обмеженими варіантами, використовуйте можливість choices
в Django для кращої читабельності коду та узгодженості з базою даних:
from django.db import models
class Product(models.Model):
STATUS_CHOICES = [
('active', 'Active'),
('inactive', 'Inactive'),
('out_of_stock', 'Out of Stock'),
]
name = models.CharField(max_length=255)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='active')
Бонус: Використовуйте перерахування Django 3.0+ для ще чистішого коду:
from django.db import models
class ProductStatus(models.TextChoices):
ACTIVE = 'active', 'Active'
INACTIVE = 'inactive', 'Inactive'
OUT_OF_STOCK = 'out_of_stock', 'Out of Stock'
class Product(models.Model):
name = models.CharField(max_length=255)
status = models.CharField(max_length=20, choices=ProductStatus.choices, default=ProductStatus.ACTIVE)
5. Ефективні пошуки по полях з індексуванням
Django дозволяє визначати індекси бази даних на рівні поля або через клас Meta
. Використовуйте їх для оптимізації продуктивності запитів:
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255)
sku = models.CharField(max_length=50, unique=True) # код товару
class Meta:
indexes = [
models.Index(fields=['sku']), # Додає індекс до поля SKU
]
## Динамічні значення полів з `callable`
Поля Django можуть приймати динамічні значення за допомогою `callable` (функції або об'єкти, які можна викликати), що дозволяє ініціалізувати поля динамічно:
from django.db import models
import uuid
class Order(models.Model):
orderid = models.UUIDField(default=uuid.uuid4, editable=False)
createdat = models.DateTimeField(autonowadd=True)
```
У цьому випадку кожен екземпляр Order
отримає унікальний order_id
без необхідності вручну встановлювати його.
7. Сигнали чудові, але менеджери моделей краще для логіки
Замість того, щоб покладатися на сигнали для загальної логіки до збереження чи після збереження, використовуйте власні менеджери моделей. Вони простіші для підтримки та тестування:
class ProductManager(models.Manager):
def active(self):
return self.filter(status='active')
class Product(models.Model):
name = models.CharField(max_length=255)
status = models.CharField(max_length=20, choices=[('active', 'Active'), ('inactive', 'Inactive')])
objects = ProductManager()
Тепер ви можете фільтрувати активні продукти так:
Product.objects.active()
8. Додавайте обмеження для цілісності даних
Django 3.2 введено CheckConstraint
, що дозволяє застосовувати правила на рівні бази даних:
from django.db.models import Q, CheckConstraint
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=10, decimal_places=2)
class Meta:
constraints = [
CheckConstraint(check=Q(price__gte=0), name='price_positive')
]
Це гарантує, що поле price
завжди буде невід'ємним.
9. Кастомні QuerySet для повторного використання
Якщо ви часто фільтруєте моделі однаковим чином, використовуйте кастомні QuerySet
(запити до бази даних) для більш чистого та повторно використовуваного коду:
class ProductQuerySet(models.QuerySet):
def expensive(self):
return self.filter(price__gte=1000)
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=10, decimal_places=2)
objects = ProductQuerySet.as_manager()
Тепер ви можете запитувати дорогі продукти так:
expensive_products = Product.objects.expensive()
10. Використовуйте можливості бази даних за допомогою сирого SQL
Для складних запитів не бійтеся використовувати сирий SQL. ORM Django дозволяє поєднувати обидва варіанти без проблем:
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255)
@classmethod
def top_selling(cls):
return cls.objects.raw('SELECT * FROM product ORDER BY sales DESC LIMIT 10')
Висновок
Моделі Django — це більше, ніж просто спосіб відображати класи Python на таблиці бази даних. Використовуючи ці поради та трюки, ви можете писати більш чистий, ефективний код, одночасно оптимізуючи продуктивність і підтримуваність.
Незалежно від того, чи ви новачок, чи досвідчений розробник Django, ці трюки допоможуть вам вивести ваші навички на новий рівень. Який з цих трюків здивував вас найбільше? Поділіться своїми думками в коментарях!
Перекладено з: 10 Django Model Tricks Developers Often Overlook