You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DRF CreateAPIView中通过slug关联外键创建评论

我来帮你搞定这个需求!要实现用Post的slug代替ID来关联创建评论,其实有两种很实用的方案,我给你详细拆解一下:

方案1:用DRF原生的SlugRelatedField处理(推荐)

这种方式最简洁,直接修改序列化器,把原来关联Post ID的字段换成关联slug的字段就行:

from rest_framework import serializers
from .models import Comments, Posts

class CommentCreateSerializer(serializers.ModelSerializer):
    # 替换原来的post字段,指定用slug匹配Post
    post = serializers.SlugRelatedField(
        queryset=Posts.objects.all(),
        slug_field='slug'  # 这里填你Post模型里的slug字段名
    )

    class Meta:
        model = Comments
        fields = ['content', 'post']

改完之后,前端发起POST请求时,直接传{"content": "你的评论内容", "post": "目标帖子的slug值"}就可以了。DRF会自动根据slug找到对应的Post对象,帮你关联到新创建的评论上,而且如果slug不存在,序列化器会自动返回验证错误,非常省心。

方案2:重写视图的perform_create方法(更灵活)

如果你不想修改序列化器,或者需要在创建评论前做一些额外逻辑(比如校验用户是否有权限评论这个帖子),可以用这种方式:

首先保持序列化器不变,但要把post字段设为只读(或者直接从fields里去掉):

class CommentCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comments
        fields = ['content']
        # 或者保留post字段但设为只读:
        # read_only_fields = ['post']

然后修改你的View,重写perform_create方法,手动通过slug找到Post再创建评论:

from rest_framework.generics import CreateAPIView
from rest_framework.permissions import IsAuthenticated
from django.shortcuts import get_object_or_404
from .models import Comments, Posts
from .serializers import CommentCreateSerializer

class CommentCreateView(CreateAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Comments.objects.all()
    serializer_class = CommentCreateSerializer

    def perform_create(self, serializer):
        # 从请求数据里拿到slug
        post_slug = self.request.data.get('post_slug')
        # 用get_object_or_404避免slug不存在时抛500错误,返回404更合理
        target_post = get_object_or_404(Posts, slug=post_slug)
        # 把找到的Post对象传给序列化器保存
        serializer.save(post=target_post)

这时候前端的POST请求要改成传{"content": "你的评论内容", "post_slug": "目标帖子的slug值"}。

小提示

如果你的Post模型里的slug不是唯一的,记得先给slug字段加上unique=True约束,不然查询的时候可能会返回多个结果导致报错哦:

class Posts(models.Model):
    title = models.CharField(max_length=512, null=True)
    slug = models.CharField(max_length=512, null=True, unique=True)  # 加上唯一约束

内容的提问来源于stack exchange,提问作者Howard Scott

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:25:52