ModelViewSet:POST时,“此字段必填”,字段为FK

时间:2019-06-01 03:12:24

标签: python django django-rest-framework

这是我当前的代码

型号:

class Author(models.Model):
    a_author= models.CharField( primary_key=True, unique=True, db_column='author_id')
    a_name = models.CharField(db_column='author_name')


class Book(models.Model):
    b_book = models.CharField( primary_key=True, unique=True, db_column='book_id')
    b_name = models.CharField(db_column='book_name')
    b_author = models.ForeignKey(
        Author,
        on_delete=models.CASCADE,
        db_column='book_author_name')

序列化器

class AuthorSerializer(serializers.ModelSerializer):
    author = serializers.CharField(source='a_author')
    name = serializers.CharField(source='a_name')
    class Meta:
        fields = ('author', 'name')

class BookSerializer(serializers.ModelSerializer):
    book = serializers.CharField(source='b_book')
    name = serializers.CharField(source='b_name')
    author = serializers.CharField(source='b_author')

    class Meta:
        fields = ('book', 'name', 'author')

    def create(self, validated_data):
        author_id = validated_data.pop('author')
        author = models.Author.objects.filter(a_author=author_id).first()
        validated_data['b_author'] = author
        return models.Book.objects.create(**validated_data)

观看次数

class BookViewSet(viewsets.ModelViewSet):
     serializer_class = BookSerializer

     def get_queryset(self):
        queryset = models.Book.objects
        author = self.kwargs.get('author')
        queryset = queryset.filter(b_author=author)
        return queryset

网址

urlpatterns = [
     path('library/<str:author_id>/', BookViewSet.as_view({'get': 'list', 'post':'create'}))
]

当前,如果我使用以下参数将消息发布到/library/123abc/{ 'name': 'test', 'author': '123abc' },它将正常工作-名称为test的book记录将创建author = 123abc。

但是现在我想从参数中取出author(由于url已经具有athor id,所以我不想在参数中再次复制它)并仅发送{'name': 'test'},它将返回消息{'author': 'this field is required'}出现400错误。我已经尝试过author = serializers.CharField(source='b_author', required=False),但是没有用。

有什么办法可以解决这个问题?我想知道是否有任何方法可以在验证params值之前在django中包含其他值...

1 个答案:

答案 0 :(得分:0)

由于您希望显示author但不写,因此需要将该字段设置为read_only

class BookSerializer(serializers.ModelSerializer):
    book = serializers.CharField(source='b_book')
    name = serializers.CharField(source='b_name')
    author = serializers.CharField(source='b_author', read_only=True)

接下来,您将希望在创建author时保存Book。 为此,您必须将其显式提供给序列化器:

class BookViewSet(viewsets.ModelViewSet):
    serializer_class = BookSerializer

    def get_queryset(self):
        queryset = models.Book.objects
        author = self.kwargs.get('author')
        queryset = queryset.filter(b_author=author)
        return queryset

    def perform_create(self, serializer):
        author = get_object_or_404(Author, pk=self.kwargs.get('author'))
        serializer.save(author= author)