'Django Rest Framework Allow a request to set a foreign key Field in CreateAPIView
A thread belongs to a board. So I would like the ThreadList view to accept a POST request with the foreign key board. What I have attempted results in an error. 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']
Solution 1:[1]
serializers.PrimaryKeyRelatedField has a required argument queryset that needs to include to tell what id of which queryset needs to be validated against.
In your case, it should be
class ThreadSerializer(serializers.ModelSerializer):
...
board = serializers.PrimaryKeyRelatedField(queryset=Board.objects.all())
...
Notes
Notice that you don't need to specify source='board.id' since django-rest-framework already handles that for you.
Extra
If there's no extra parameters that will be pass into serializers.PrimaryKeyRelatedField to change the default behavior, you can just include board in class Meta's fields and no need to use serializers.PrimaryKeyRelatedField manually.
class ThreadSerializer(serializers.ModelSerializer):
post = PostSerializer(many=True, read_only=True)
class Meta:
model = Thread
fields = ['id', 'title', 'post', 'board']
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | annonymous |
