новый read_only + поведение по умолчанию drf 3.8 дает ошибку - PullRequest
0 голосов
/ 17 октября 2019

Вот пример ошибки:

Модель:

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 исключены из доступных для записи полей, поэтому вы должны явно сохранить эти поля, написав execute_create или переопределив функции создания, обновления и сохранения сериализатора

, поэтому я написал это в наборе

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

для справки этот perfrom_create вызывается внутри метода создания mixins.CreateModelMixin

   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')]}

, и этот тест не выполняется в строке ниже функции create, то есть он даже не достигает execute_createчто я переоценил.

serializer.is_valid(raise_exception=True)

Данные неверны.

нужна помощь.

...