Как сделать вещи менее сложными с менеджерами моделей Django
23 февраля 2023 г.В этой статье мы узнаем о менеджерах моделей Django. Недавно, когда я просматривал r/django сообщество Reddit, я был рад помочь другим разработчикам Django исправить их ошибки. .
Я просмотрел несколько сообщений и прочитал задачи, чтобы начать, и нашел первую задачу, которую мне понравилось решать.
Проблема заключалась в следующем: «Я хотел бы применить логику к своим приложениям, записав методы в models.py. Каков наилучший способ сделать это? Документация отлично подходит для основ, но я разочаровываюсь, работая над применением бизнес-логики за пределами views.py. Любые хорошие ресурсы по этому типу потока? Бизнес-логика в models.py?”
Возможно, вы тоже иногда сталкивались с этим разочарованием, потому что Django — это надежный фреймворк для перфекционистов со сроками; он ожидает, что мы сами разберемся с этим (Или я так думал, потому что этот вопрос очень хорошо освещен в документации, которую, если вы похожи на меня, вы могли ее не читать).
Итак, я дал им решение, которое я обычно использую для написания повторяющихся или общих запросов фильтров Django в файле models.py, где вы определяете свои модели, например:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=70)
# ...
def get_howto_guides(self):
return Post.objects.filter(title__istartswith="how to")
Сначала я не видел в этом ничего плохого. Я все еще учился и пытался заставить вещи работать. Но вскоре люди на Reddit указали, что такой подход не оптимален, и что лучшее место для этого — менеджер.
Менеджер управляет набором моделей (по сути, таблицей SQL), а модель — это просто строка в этой таблице (она не должна знать о других строках). И мальчик, я был смущен.
Вскоре я понял, что по мере роста нашей кодовой базы наши модели будут раздуваться из-за бизнес-логики, которая лучше подходит для наших менеджеров моделей.
Только когда я наткнулся на концепцию менеджеров моделей, я понял, что есть лучший способ организовать мой код (если вы используете Reddit, присоединяйтесь к r/django. Каждый день вы будете узнавать так много нового).
Я узнал, что менеджеры моделей — это способ инкапсулировать операции и запросы на уровне модели простым и модульным способом.
Как это сделать
По умолчанию Django добавляет Manager
с именем objects
в каждый класс модели Django. Однако, если вы хотите использовать objects
в качестве имени поля или если вы хотите использовать имя, отличное от objects
для Manager
, вы можно переименовать для каждой модели.
Чтобы переименовать Manager
для данного класса, определите атрибут класса типа models.Manager()
для этой модели. Например:
from django.db import models
class Post(models.Model):
# ...
how_to = models.Manager()
Здесь Post.how_to
генерирует AttributeError
, а Post.how_to.all()
возвращает все объекты из этого менеджера.
Теперь я могу поместить всю свою бизнес-логику о том, «Как направлять сообщения», в свой менеджер моделей «how_to». Например, если мне нужны все посты, начинающиеся с «Как сделать», или статьи типа «как сделать-x», я напишу следующий менеджер моделей отдельно для таких постов.
from django.db import models
class HowtoPostsManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(title__istartswith="how to")
# istartswith lookup field is used to
# lookup case-insensitive titles.
class Post(models.Model):
# ...
objects = models.Manager() # Default Manager
how_to = models.HowtoPostsManager() # our custom manager
Теперь Post.objects.all()
вернет все сообщения из базы данных, а Post.how_to.all(),
вернет только сообщения, заголовок которых начинается с « Как».
Этот пример также указывает на еще один интересный метод: использование нескольких менеджеров в одной и той же модели. Вы можете прикрепить к модели столько экземпляров Manager()
, сколько захотите. Это неповторяющийся способ определения общих «фильтров» для ваших моделей.
Наборы запросов как менеджеры моделей
Вы также можете определить общие фильтры в качестве менеджеров моделей в своих моделях Django. Например:
from django.db import models
class HowtoQuery(models.QuerySet):
def title_starts_with_howto(self):
return self.filter(title__istartswith="how to")
class Post(models.Model):
# ...
objects = models.Manager() # Default Manager
how_to = HowtoQuery.as_manager() # our custom manager
# This will be identicle to the previous code example,
# we looked at
Не каждый метод QuerySet
имеет смысл на уровне Manager
; например, django предотвращает копирование метода QuerySet.delete()
в класс Manager
.
С помощью менеджеров моделей я мог писать собственные методы для своих моделей, которые обрабатывали сложную логику, фильтрацию и агрегирование. Я также мог создавать новые наборы запросов, соответствующие потребностям моего приложения, что упрощало повторное использование кода в моих представлениях.
Когда я начал больше использовать менеджеры моделей в своих приложениях, я обнаружил, что мой код становится чище и легче для чтения. Я также мог удалить большую часть кода из своих моделей и сохранить свою бизнес-логику ближе к тому месту, где она должна быть.
Оглядываясь назад, трудно поверить, что я не знал о менеджерах моделей даже после того, как кодировал в Django в течение значительного периода времени.
Но я благодарен за то, что столкнулся с этой концепцией, поскольку она полностью изменила способ написания кода и помогла мне стать лучшим разработчиком Django.
Итак, всем, кто борется со сложными представлениями и запутанной кодовой базой, я настоятельно рекомендую изучить возможности менеджеров моделей в Django. Вы можете быть удивлены тем, насколько они могут упростить ваш код и улучшить общий опыт разработки.
Также опубликовано здесь р>
Оригинал