【问题标题】:Django Rest Framework why is ModelSerializer creating objects with all null fields?Django Rest Framework 为什么 ModelSerializer 创建具有所有空字段的对象?
【发布时间】:2018-07-02 22:39:09
【问题描述】:

我有一个名为 Package 的模型。我正在尝试使用 Django Rest Framework 中的 ModelSerializer 在我的数据库中保存新实例并更新它的现有实例。我想从 API 服务器发出所有包的 GET 请求,并将它们保存为新对象或更新我数据库中的现有对象。

我在我的数据库中成功创建了新的 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)

序列化器.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= 集的字段。

感谢您的帮助。

更新: 我已经尝试在 shell 中遍历该过程,它可以更清晰地了解正在发生的事情:

>>> 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)

【问题讨论】:

  • response 是否包含数据?它可以是空的,所以你的字段也是空的
  • @AlexandrTatarinov 是的,我从 GET 请求中得到了预期的响应。如果我打印出结果,它会打印一个包含 12 个有序字典的列表,这就是我试图从中创建模型对象的内容。
  • 现在看来问题与 s.is_valid() 返回一个空的 OrderedDict 有关,但我不知道这是怎么回事
  • 它表明您提供给序列化程序的data 也具有None 值,因此序列化程序只是将它们从validated_data 中删除。在您的代码中找不到任何可疑的东西,您确定要将带有数据的 dict 传递给序列化程序吗?无论如何它不应该变异data....
  • @AlexandrTatarinov 在调试器中运行它表明我传递给序列化程序的 dict 具有正确的数据:s = PackageSerializer(data=item) s: PackageSerializer(data={'Id': 33101, 'Label': 1234ABCD5678EFGH9123', 'PackageType': 'Product', --snip--} 在返回验证数据之前,这些字段不会设置为无。

标签: python django django-models django-rest-framework


【解决方案1】:

我想通了!

答案很明显,因此有点难以理解。我只是在 Package 模型中的字段与输入到 ModelSerializer 的 JSON 字典中的键之间存在不匹配。

例如,模型中的label 和JSON 中的'Label',模型中的package_type 和JSON 中的'PackageType'

事后看来,这很明显。序列化程序如何知道将值放置在哪些字段中?

is_valid() 在每个字段上都返回None,因为它正在获取有效数据作为输入,但不知道将其放在哪里。

事后看来,在调试过程中,我还用null=Trueblank=True 暂时允许某些必填字段为空,从而使自己陷入了困境。这允许验证在必填字段上成功完成,而实际上它没有获得适当的数据。

【讨论】:

    【解决方案2】:

    我认为你的观点是错误的

    这是什么:

    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()
    

    【讨论】:

      猜你喜欢
      • 2015-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-27
      • 1970-01-01
      • 2021-08-08
      • 1970-01-01
      • 2013-08-26
      相关资源
      最近更新 更多