Где разместить логику изменения состояния одной сущности другой сущностью в Django REST Framework?

Представьте себе простое приложение, в котором пользователь может публиковать некоторые запросы (например, ему нужна помощь, еда), а другие пользователи могут через чат дать ответ на этот запрос. Вот мои упрощенные модели:

class UserRequest(models.Model):
    ACTIVE = 'active'
    INACTIVE = 'inactive'
    STATUS_CHOICES = [
        (ACTIVE, 'Active'),
        (INACTIVE, 'Inactive'),
    ]

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    request_text = models.TextField()
    status = models.CharField(max_length=8, choices=STATUS_CHOICES, default=INACTIVE)


class RequestChat(models.Model):
    user_request = models.ForeignKey(UserRequest, on_delete=models.CASCADE)


class ChatMessage(models.Model):
    text = models.TextField()
    chat = models.ForeignKey(RequestChat, on_delete=models.CASCADE)

Мне нужно реализовать такую функциональность:

Когда создано хотя бы одно сообщение в чате (записано в чат) - статус связанного запроса должен быть изменен с INACTIVE на ACTIVE.

Нужно ли поместить эту логику в метод save() модели ChatMessage или обработать ее с помощью сигнала Django? Или, возможно, есть другой способ сделать это? Кроме того, не могли бы вы порекомендовать какие-либо ресурсы, например, книги, статьи или видео, которые содержат руководство по этой теме?

Как и во всем, что касается архитектуры программного обеспечения: это зависит.

Тема, о которой вы спрашиваете, - проектирование агрегатов. Существует множество материалов. Я думаю, что в книге Вернона Implementing Domain Driven Design есть хороший пример по агрегированному проектированию. Мне кажется, я также нашел полезной эту статью, состоящую из 3 частей, посвященных агрегатному проектированию.

Ну, это не должно быть в методе сохранения. Метод сохранения относится к персистентным методам и не должен знать бизнес-правила о том, когда UserRequest становится активным или нет.

Должен быть некий объект домена, который знает, когда UserRequest становится АКТИВНЫМ. Этим доменным объектом может быть сам UserRequest, то есть UserRequest - это корневой агрегат, а ChatMessage - сущность внутри этого агрегата. При извлечении UserRequest извлекаются все ChatMessage. Добавление нового чат-сообщения осуществляется через корневой агрегат (userRequest.addChatMessage). Когда сообщение чата отправлено, вы можете изменить его статус на активный. Недостатком этого способа является то, что загрузка всех сообщений чата может быть неэффективной, а также то, что он создает много непредвиденных ситуаций в зависимости от того, какие операции разрешено выполнять пользователям (например: поскольку все сообщения чата изменяются через запрос, для сохранения последовательности в любой момент времени можно выполнить только одно изменение).

Другая альтернатива - сделать их разными агрегатами и использовать конечную согласованность. Когда ChatMessage сохраняется, он испускает событие, которое модуль UserRequest может прослушать и изменить статус на активный. В модуле UserRequest должна быть служба Domain, которая знает правила о том, когда запрос становится активным.

Оба подхода подходят, все зависит от особенностей вашей системы и бизнеса.

Вернуться на верх