从有效负载创建时 Django Rest Framework Not Null 错误

Django Rest Framework Not Null Error when creating from payload

我正在尝试编写一个测试来检查我的 Viewset 的创建方法是否正常工作:

@pytest.mark.django_db
def test_create(admin_user):
    parent = factories.ParentFactory()
    payload = {
        'name': 'child',
        'parent_id': parent.pk,
    }
    view = views.ParentViewSet.as_view({'post': 'create'})
    request = factory.post('/', payload, format='json')
    force_authenticate(request, user=admin_user)
    response = view(request)
    assert response.status_code == status.HTTP_201_CREATED
    assert models.Child.objects.count() == 1
    child = models.Child.objects.first()
    assert child.name == 'child'

但是,当我 运行 代码时出现以下错误:

psycopg2.errors.NotNullViolation: null value in column "parent_id" violates not-null constraint

但是 Parent 创建方法的测试 运行 没问题:

def test_create(admin_user):
    payload = {
        'name': 'parent',
        'children': [
            {
                'name': 'child',
            }
        ],
    }
    view = views.ParentViewSet.as_view({'post': 'create'})
    request = factory.post('/', payload, format='json')
    force_authenticate(request, user=admin_user)
    response = view(request)
    assert response.status_code == status.HTTP_201_CREATED
    assert models.Parent.objects.count() == 1
    season = models.Parent.objects.first()
    assert season.name == 'parent'
    assert season.children.count() == 1

有人可以告诉我为子测试创建编写有效负载的正确方法吗?

编辑:

serializers.py

class ChildSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Child
        fields = ['id', 'name']


class ParentSerializer(serializers.ModelSerializer):
    children = ChildSerializer(many=True)

    class Meta:
        model = models.Parent
        fields = ['id', 'name', 'children']

    def create(self, validated_data):
        children = validated_data.pop('children')
        parent = super().create(validated_data)
        for child in children: 
            child['parent'] = parent
        self.fields['children'].create(children)
        return parent

views.py

class ParentViewSet(
    viewsets.GenericViewSet,
    mixins.CreateModelMixin,
    mixins.ListModelMixin,
    mixins.RetrieveModelMixin,
    mixins.DestroyModelMixin,
):
    queryset = models.Parent.objects.all().prefetch_related(
        'children'
    )
    serializer_class = serializers.ParentSerializer


class ChildViewSet(
    viewsets.GenericViewSet,
    mixins.CreateModelMixin,
    mixins.ListModelMixin,
    mixins.RetrieveModelMixin,
    mixins.DestroyModelMixin,
):
    queryset = models.Child.objects.all().prefetch_related(
        'children'
    )
    serializer_class = serializers.ChildSerializer

我认为您在子模型中有一个字段 "parent",但是因为您没有在 ChildSerializer 中包含该字段,即使您在请求中发送它也是如此body,它在创建 Child 实例时不包含在内,因此会出现错误。你有几种方法可以解决它

1 - 您可以将父字段添加到 ChildSerializer:

class ChildSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Child
        fields = ['id', 'name', 'parent']

并像这样发送请求:

payload = {
    'name': 'child',
    'parent': parent.pk,
}

2 - 如果你不想这样,你可以保持 ChildSerializer 现在的样子,并且只在保存子实例时添加父实例,像这样:

class ChildViewSet(
    ...
):
    queryset = models.Child.objects.all().prefetch_related('children')
    serializer_class = serializers.ChildSerializer

    def perform_create(self, serializer):
        serializer.save(parent_id=self.request.data.get('parent'))

同样,您需要像这样发送请求:

payload = {
    'name': 'child',
    'parent': parent.pk,
}

但是在第二种情况下,您没有在请求验证中包括父字段,如果客户端没有发送父字段或在那里发送无效值,您将得到一个异常。如果您要使用此解决方案,我建议您也以某种方式验证父字段。