Как сделать вещи менее сложными с менеджерами моделей Django

Как сделать вещи менее сложными с менеджерами моделей 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. Вы можете быть удивлены тем, насколько они могут упростить ваш код и улучшить общий опыт разработки.


Также опубликовано здесь


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE