【问题标题】:validate if instance exists django验证实例是否存在 django
【发布时间】:2020-11-20 05:15:09
【问题描述】:

我正在 DRF 上构建一个 REST Api。我有一个来自 rest_framework.viewsets 的 ModelViewSet 端点。

我有一个帖子和一个评论模型。每条评论都属于一个帖子。所以我定义了 2 个端点,类似于:

1) router.register(r"posts", views.PostView
2) router.register(r"(?P<pk>[^/.]+)/comments", views.CommentView

它们都继承自 ModelViewSet,因此我可以对它们执行 CRUD 操作。

我对第二个端点有疑问。由于我们为帖子创建 cmets,因此我从 posts/int:pk/cmets 获得了一个帖子 pk。但问题是当我在这个端点上做一个 GET 请求时,它会返回所有 cmets 的列表,但我需要那些属于一个帖子(url 中的 id)。当我尝试在此端点上发出 POST 请求时,如果帖子不存在,它会引发 DoesNotExist 错误,这是合乎逻辑的。

到目前为止我所做的是:

  1. 重新定义了 get_queryset() 以仅检索属于特定帖子的对象。如果帖子不存在,它会返回一个空列表(尽管我认为它应该引发 404)
  2. 在我的序列化程序中重新定义了 validate() 以检查帖子是否存在。如果没有则返回 404

但是当我检查posts/int:pk/cmets/int:pk 上的PUT、DELETE、PATCH 方法时,它也不会考虑post 实例,即即使post 不存在,它也会允许这些操作我认为这是错误的。

ModelViewSet 类中是否有一个方法可以在每次请求时触发并检查 post 实例是否存在?这样我就不必为了检查它而重新定义每个 CRUD 方法。

编辑

评论视图

class CommentView(ModelViewSet):
    queryset = Comment.objects.all()
    serializer_class = CommentSerializer
    lookup_url_kwarg = 'pk2'

    def get_queryset(self):
        queryset = Comment.objects.filter(post=self.kwargs.get('pk'))
        return queryset

    def perform_create(self, serializer, **kwargs):
        post = get_object_or_404(Post, pk=self.kwargs.get('pk'))
        serializer.save(author=self.request.user, post=post)

【问题讨论】:

  • 你能展示你的 CommentView 代码吗?
  • 嗨,我已经编辑了帖子
  • 尝试删除行 `queryset = Comment.objects.all()` 它可能会覆盖您对 get_queryset 的定义。只需要其中一个。

标签: django django-rest-framework


【解决方案1】:

不妨看看drf-nested-routers package

如果它不能解决你的问题,也许你想要的是标准的路由器注册:

router.register(r"posts", views.PostView)
router.register(r"comments", views.CommentView)

然后在列出 cmets 时使用 django-filter 之类的包通过查询参数进行过滤:/comments/?post=&lt;id&gt;。创建评论时,只需在请求正文中发送帖子 ID(不要忘记在 CommentSerializer 中包含“帖子”字段)

【讨论】:

  • 我相信将路线一分为二并在正文中发送一个帖子 ID 肯定会完成这项工作。看起来重新定义 get_queryset 和 perform_create 也完成了这项工作。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-17
  • 1970-01-01
  • 1970-01-01
  • 2012-12-13
  • 1970-01-01
  • 2020-03-31
相关资源
最近更新 更多