新的 read_only + drf 3.8 的默认行为给出错误

问题描述 投票:0回答:1

这是错误的示例:

型号:

from django.db import models

class Hero(models.Model):
    alias = models.(max_length=60)
    character = models.ForeignKey(User, on_delete=models.CASCADE)

def __str__(self):
    return self.name

序列化器:

class HeroSerializer(serializers.ModelSerializer):
    character = HyperlinkedRelatedField(read_only=True, default=<some user object>)
    class Meta:
        model = Hero
        fields = ('character', 'alias')

视图集:

class HeroViewSet(NestedViewSetMixin,
                         mixins.CreateModelMixin,
                         mixins.UpdateModelMixin,
                         viewsets.ReadOnlyModelViewSet):
    queryset = Hero.objects.all()
    serializer_class = HeroSerializer

测试:

def test_created_successfully(self):
    alias = 'blab blah'
    response = self.client.post(self.url, {'name': name})
    self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.data)

现在通过的测试是drf 3.7.7

当我升级到 drf 3.8.2 时,这个错误开始发生

django.db.utils.IntegrityError: null value in column "character_id" violates not-null constraint
DETAIL:  Failing row contains (blah_blah, null).

他们说现在默认 + read_only 字段被排除在可写字段之外,因此您必须通过编写 Perform_create 或重写序列化器的 create 、 update 和 save 函数来显式保存这些字段

所以我在视图集中写了这个

def perform_create(self, serializer):
    serializer.save(character=<some user object>)

供参考,这个 perfrom_create 在 mixins.CreateModelMixin 的 create 方法中被调用

   def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

所以它在这里工作,但现在如果相同的序列化器更改为(字符字段更改为名称,并且名称的源为“字符字段”。

class HeroSerializer(serializers.ModelSerializer):
    name = HyperlinkedRelatedField(source='character', read_only=True, default=<some user object>)
    class Meta:
        model = Hero
        fields = ('name', 'alias')

我的测试失败了

self.assertEqual(response.status_code, status.HTTP_201_CREATED, response.data)
AssertionError: 400 != 201 : {'character': [ErrorDetail(string='This field is required.', 
code='required')]}

这个测试在创建函数的下面一行中失败,即这甚至没有达到我重写的perform_create。

serializer.is_valid(raise_exception=True)

数据无效。

需要帮助。

python django api django-rest-framework django-serializer
1个回答
0
投票

在这种情况下必须使用

allow_null
HyperlinkedRelatedField
参数。

© www.soinside.com 2019 - 2024. All rights reserved.