Модельный метод разделения концерна - PullRequest
1 голос
/ 16 апреля 2019

Игрушечный пример: в моем проекте Django у меня есть два приложения: Core и Blog

Core приложение обеспечивает функциональность пользователей;Модель пользователя, вход в систему, регистрация и т. Д. Блог * Приложение 1008 * обеспечивает функциональность блогов;Блоги, комментарии, категории и т. Д.

Предметом интереса являются модели:

# core/models.py

class User(models.Model):
    firstName = models.CharField(max_length=100)
    lastName = models.CharField(max_length=100)
    email = models.EmailField()
    ...

# blog/models.py

class BlogPost(models.model):
    title = models.CharField(max_length=100)
    post = models.TextField()
    owner = models.ForeignKey('core.User', on_delete=models.CASCADE)
    ...

Я использую DRF и один из моих ViewSets, в который я возвращаюсь.список всех BlogPosts для текущего пользователя.Для этого мне нужно создать QuerySet

Я могу создать метод модели для объекта пользователя, например, так:

# core/models.py

class User(models.Model):
    ...

    def viewable_blogs(self):
        return BlogPost.objects.filter(owner=self.id)

И просто использовать его так:

class BlogPostViewSet(viewsets.ModelViewSet):
    serializer_class = BlogPostSerializer

    def get_queryset(self):
        return self.request.user.viewable_blogs.all()

Это кажется мне совершенно неправильным и делает меня немного некомфортным, поскольку нарушает принцип единой ответственности.т.е. пользовательская модель не должна ничего знать о других моделях.

Я пришел из других фреймворков, таких как express, springboot и т. д., я бы создал BlogService и поместил туда функциональность viewable_blogs:

class BlogPostViewSet(viewsets.ModelViewSet):
    serializer_class = BlogPostSerializer

    def get_queryset(self):
        return BlogService.getBlogsForUser(self.request.user)

Есть ли рекомендуемый Django способ обеспечить инкапсуляцию?Делает ли классы обслуживания Django способ сделать это?

1 Ответ

2 голосов
/ 16 апреля 2019

Для связанных моделей (например, User и BlogPost), я думаю, Django автоматически создает RelatedManager для вашего User экземпляра с атрибутом, называемым blogpost_set.

Так что вам следуетбыть в состоянии получить сообщения в блоге для определенного пользователя с чем-то вроде:

user = User(pk=1)
user.blogpost_set.all()

Это в основном та же функциональность, что вы делали вручную в вашем viewable_blogs методе, но Django склоняется к использованию встроенного- в «менеджерах» делать реляционные наборы запросов.Я бы сказал, что создание BlogService, вероятно, не будет идеальным, поскольку оно добавляет дополнительный слой к отношениям между моделями, а Python склоняется к более простым подходам.

См .:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...