Django Rest Framework, почему ModelSerializer создает объекты со всеми пустыми полями? - PullRequest
0 голосов
/ 03 июля 2018

У меня есть модель под названием Package. Я пытаюсь сохранить новые экземпляры и обновить существующие экземпляры в моей базе данных с помощью ModelSerializer из Django Rest Framework. Я хочу сделать запрос GET для всех пакетов с сервера API и сохранить их как новые объекты или обновить существующие в моей базе данных.

Я успешно создаю новые объекты Package в моей базе данных, однако все поля пусты.

view.py

def pckgs(request):
    result = {}
    message = ""
    save_message = ""

    endpoint = "removed for stack overflow"

    response = requests.get(endpoint, auth=auth, params=params)
    if response.status_code == 200:  # SUCCESS
        result = response.json()
        s = PackageSerializer(data=result, many=True)
        if s.is_valid():
            s.save()
        else:
            save_message = s.errors
    else:
        message = response.status_code + " there was an error"

    context = {'result': result, 'message': message, 'response_url': response.url, 'save_message': save_message}
    return render(request, 'core/pckgs-active.html', context)

serializers.py

class PackageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Package
        fields = '__all__'

    def create(self, validated_data):
        return Package.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.label = validated_data.get('label', instance.label)
        instance.package_type = validated_data.get('package_type', instance.package_type)
    # ---snip--- there are 32 fields
        instance.save()
        return instance

Я не получаю ошибок от s.errors. При первой попытке использования этого метода я получил несколько ошибок, которые не могли быть пустыми. Я временно допустил нулевые значения в этих полях, и ошибки исчезли. Что-то заставляет сериализатор сохранять нулевое значение для каждого поля?

Единственные поля со значениями - это поля с атрибутом choices= и набором default=.

Спасибо за вашу помощь.

UPDATE: Я попытался пройти процесс в оболочке, которая дает более четкое представление о том, что происходит:

>>> for item in result:
...     s = PackageSerializer(data=item)
...     if s.is_valid():
...             print(s.validated_data)
...             print(s.data)
... 
OrderedDict()
{'label': None, 'source_harvest_names': None, 'room_id': None, 'room_name': 
None, 'quantity': None, 'unit_of_measure': None, 'unit_of_measure_abbrev': 
None, 'patient_license_num': None, 'product_id': None, 'product_name': None, 
'product_category_name': None, 'packaged_date': None, 'lab_testing_state_date': 
None, 'production_batch_number': None, 'remediation_date': None, 
'received_from_manifest_number': None, 'received_from_facility_license_number': 
None, 'received_from_facility_name': None, 'received_date_time': None, 
'archived_date': None, 'finished_date': None}

Почему я теряю все значения в этом процессе? Когда я бегу

for item in result:
    print(item)

Я получаю каждый дикт с правильным ключом: пары значений, имеющие значения.

Аналогично, следующее утверждение также все еще печатает правильные значения:

for item in result:
    s = PackageSerializer(data=item)
    print(s)

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Я понял это!

Ответ был очевиден, и поэтому его немного сложнее поймать. У меня просто было несоответствие между полями в модели пакета и ключами в словаре JSON, передаваемыми в ModelSerializer.

Например, label в модели и 'Label' в JSON, package_type в модели и 'PackageType' в JSON.

Оглядываясь назад, это очевидно. Как сериализатор узнает, в какие поля помещать значения?

is_valid() возвращал None в каждом поле, потому что он получал действительные данные в качестве входных данных, но не знал, куда их поместить.

В ретроспективе я также выстрелил себе в ногу, поскольку отладка временно позволила некоторым обязательным полям обнулиться с null=True и blank=True. Это позволило успешно завершить проверку в обязательных полях, когда в действительности не было получено соответствующих данных.

0 голосов
/ 04 июля 2018

Я думаю, что вы ошиблись

что это:

response = requests.get(endpoint, auth=auth, params=params)

Вместо этого вы должны использовать этот код:

response = request.data

но если у вас нет проблем с модулем обобщений. используйте этот модуль, пожалуйста

class MyCreateAPIView(generics.CreateAPIView):
    serializer_class = PackageSerializer
    queryset = Package.objects.all()

class MyRetrieveUpdateAPIView(generics.RetrieveUpdateAPIView):
    serializer_class = PackageSerializer
    queryset = Package.objects.all()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...