【问题标题】:Model method separation of concern模型方法关注点分离
【发布时间】:2019-09-06 01:58:52
【问题描述】:

玩具示例:在我的 Django 项目中,我有两个应用程序:CoreBlog

核心应用为用户提供功能;用户模型、登录注销、注册等
博客应用提供博客功能;博客、评论、类别等

感兴趣的主题是模型:

# 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 的一种方式吗?

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    对于相关模型(即UserBlogPost),我认为Django 会自动为您的User 实例创建一个RelatedManager,其属性名为blogpost_set

    因此,您应该能够通过以下方式获取特定用户的博客文章:

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

    这与您在 viewable_blogs 方法中手动完成的功能基本相同,但 Django 倾向于使用内置的“管理器”来执行关系查询集。我会说创建BlogService 可能不是理想的,因为它为模型之间的关系添加了一个额外的层,而 Python 倾向于使用更简单的方法。

    见:

    【讨论】:

    • 这在本例中可行,但如果我需要一个更复杂的查询,例如“返回此用户的所有帖子用户的管理员帖子”,那么这将不起作用
    • 对于更复杂的查询,您可以创建一个自定义管理器来根据您的条件获取查询集。见:docs.djangoproject.com/en/2.2/topics/db/managers/…
    • 很高兴这对你有用!我发现其他语言的许多概念和设计模式可以使用不同的术语在 Django 中表达,但在某些方面,一旦你习惯了 Django 的做事方式,它们实际上会更简单。 Django 非常擅长确保其大部分功能都是高度可定制的。
    猜你喜欢
    • 2010-12-09
    • 2014-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-18
    • 2016-05-30
    • 1970-01-01
    相关资源
    最近更新 更多