Django Rest Framework 允许请求在 CreateAPIView 中设置外键字段

Django Rest Framework Allow a request to set a foreign key Field in CreateAPIView

一个线程属于一个板。所以我希望 ThreadList 视图接受带有外键 board 的 POST 请求。我的尝试导致错误。 AssertionError: Relational field must provide a queryset argument, override get_queryset, or set read_only=True

serializers.py

class ThreadSerializer(serializers.ModelSerializer):
 
    post = PostSerializer(many=True, read_only=True)
    # board = serializers.ReadOnlyField(source='board.id')
    board = serializers.PrimaryKeyRelatedField(source='board.id')

    class Meta:
        model = Thread
        fields = ['id', 'title', 'post', 'board']

views.py

class ThreadList(generics.ListCreateAPIView):

    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    def perform_create(self, serializer):
        serializer.save(thread_admin=self.request.user)

    queryset = Thread.objects.all()
    serializer_class = ThreadSerializer

models.py

class Board(models.Model):

    name = models.CharField(max_length=25, unique=True)
    created = models.DateTimeField(auto_now_add=True)
    board_admin = models.ForeignKey('auth.User', on_delete=models.CASCADE, related_name='board_admin')
    board_moderator = models.ManyToManyField(User, related_name='board_moderator')

    class Meta:
        ordering = ['created']


class Thread(models.Model):

    title = models.CharField(max_length=250)
    created = models.DateTimeField(auto_now_add=True)
    thread_admin = models.ForeignKey('auth.User', on_delete=models.CASCADE, related_name='thread')
    board = models.ForeignKey(Board, on_delete=models.CASCADE, related_name="thread")

    class Meta:
        ordering = ['created']

serializers.PrimaryKeyRelatedField 有一个必需的参数 queryset,需要包含该参数以告知需要验证哪个 ID queryset

你的情况应该是

class ThreadSerializer(serializers.ModelSerializer):
    ...
    board = serializers.PrimaryKeyRelatedField(queryset=Board.objects.all())
    ...

备注

请注意,您不需要指定 source='board.id',因为 django-rest-framework 已经为您处理了。

额外

如果没有额外的参数将传递给 serializers.PrimaryKeyRelatedField 以更改默认行为,您可以只在 class Metafields 中包含 board 而没有需要手动使用 serializers.PrimaryKeyRelatedField

class ThreadSerializer(serializers.ModelSerializer):
    post = PostSerializer(many=True, read_only=True)

    class Meta:
        model = Thread
        fields = ['id', 'title', 'post', 'board']