Cannot post entry specifying specific id if the id

2019-07-08 10:10发布

问题:

I have two models, Book and ReadBy as specified in models.py:

class Book(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    owner = models.ForeignKey(MyUser)

class ReadBy(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    owner = models.ForeignKey(MyUser)
    book = models.ForeignKey(Book)

views.py:

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def pre_save(self, obj):
        obj.owner = self.request.user

class ReadByViewSet(viewsets.ModelViewSet):
    queryset = ReadBy.objects.all()
    serializer_class = ReadBySerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def pre_save(self, obj):
        obj.owner = self.request.user

serializers.py:

class BookSerializer(serializers.ModelSerializer):
    readby = serializers.SerializerMethodField('get_ready_by')

    def get_read_by(self, obj):
        user = self.context['request'].user
        book = obj
        return ReadBy.objects.filter(book=book, owner=user).exists()

    class Meta:
        model = Book
        fields = ('id', 'created', 'owner', 'readby')

class ReadBySerializer(serializers.ModelSerializer):
    owner = serializers.Field(source='owner.id')
    book = serializers.Field(source='book.id')

    class Meta:
        model = ReadBy
        fields = ('id', 'created', 'owner', 'book')

Book is a ForeignKey in ReadBy. The reason for this is that I want to see if the book has been read by defining the readby field in BookSerializer to true or false.

Now when I try to POST a ReadBy item I cannot explicitly set the book_id, even if I try do I still get the same error:

"Column 'book_id' cannot be null"

What I need to know is how I can explicitly specify book_id to be able to "read" a book.

Thanks.

回答1:

class ReadBy(models.Model):
    ... snip ...
    book = models.ForeignKey(Book, null=True, blank=True)


回答2:

OK I solved this.

I forgot to define the book field in the ReadBySerializer as PrimaryKeyRelatedField:

book = serializers.PrimaryKeyRelatedField(source='book.id')

In fact it seems like I can remove this line altogether since PrimaryKeyRelatedField is default if nothing is specified.