【问题标题】:Django Rest Framework - How to restructure json response?Django Rest Framework - 如何重构 json 响应?
【发布时间】:2016-06-18 19:30:25
【问题描述】:

我正在使用 Django Rest Framework(连同 rest_framework_mongoengine)并覆盖我的序列化程序的 to_representation() 以发回我自己的自定义 JSON 对象。一切正常,但 JSON 字段的顺序搞砸了。请告诉我如何重新排序/重组返回的 JSON 对象。序列化器如下所示:

class PharmacySerializer(DocumentSerializer):
    bank_account = serializers.DictField(child=serializers.CharField(), required=False)

    class Meta:
        model = Pharmacy
        fields = (
            'id', 'name', 'email', 'mobile', 'address_line_1', 'address_line_2',
            'city', 'state', 'zip', 'created_by', 'created_on', 'last_updated_by', 'license_number',
            'bank_account', 'last_updated_on', 'is_email_verified', 'is_mobile_verified', 'is_active')
        read_only_fields = ('created_by', 'created_on', 'last_updated_by', 'last_updated_on', 'is_active')

    def to_representation(self, pharmacy):
        return {
            'id': str(pharmacy.id),
            'name': pharmacy.name,
            'email': pharmacy.email,
            'mobile': pharmacy.mobile,
            'address_line_1': pharmacy.address_line_1,
            'address_line_2': pharmacy.address_line_2,
            'city': pharmacy.city,
            'state': pharmacy.state,
            'zip': pharmacy.zip,
            'created_by': pharmacy.created_by,
            'created_on': pharmacy.created_on,
            'last_updated_by': pharmacy.last_updated_by,
            'license_number': pharmacy.license_number,
            'bank_account': {
                'bank_name': pharmacy.bank_account.bank_name,
                'account_number': pharmacy.bank_account.account_number,
                'account_type': pharmacy.bank_account.account_type
            },
            'last_updated_on': pharmacy.last_updated_on,
            'is_email_verified': pharmacy.is_email_verified,
            'is_mobile_verified': pharmacy.is_mobile_verified,
            'is_active': pharmacy.is_active
        }

我得到的回应是:

[
    {
        "city": "City",
        "name": "Some Pharmacy",
        "zip": "778372",
        "mobile": "9880082229",
        "license_number": "SP22",
        "is_mobile_verified": false,
        "is_active": true,
        "created_on": "2016-06-18T19:01:02.901",
        "created_by": null,
        "email": "somepharmacy@gmail.com",
        "state": "State",
        "last_updated_by": null,
        "is_email_verified": false,
        "last_updated_on": "2016-06-18T19:01:02.901",
        "address_line_2": null,
        "id": "57659a6ea3b6561c0f20265e",
        "bank_account": {
            "bank_name": "HSBC",
            "account_type": "Savings",
            "account_number": "663822553"
        },
        "address_line_1": "Address"
    }
]

我希望它与 to_representation() 的返回字典的顺序相同

【问题讨论】:

  • 您是否尝试过使用OrderedDict
  • @RahulGupta 我正在覆盖 to_representation() 因为默认情况下它无法处理“bank_account”,因为“bank_account”是一个 EmbeddedDocument(请注意,我正在使用带有 DRF 的 MongoEngine)
  • @heaVenShaker 你试过EmbeddedDocumentSerializer bank_account 字段吗?
  • @RahulGupta 成功了!谢谢你的小费!我使用了 EmbeddedDocumentSerializer,它可以按我的意愿完美运行!不知何故,我错过了 EmbeddedDocumentSerializer,并认为它不存在。我的错。所以这个问题的答案仍然是使用 OrderedList,但是对于我的使用,你的建议更适合!
  • @heaVenShaker 太棒了!推荐的方法是使用EmbeddedDocumentSerializer,而不需要覆盖to_representation。已更新我的答案以包含此内容。

标签: python django django-rest-framework


【解决方案1】:

如果你想保持响应键的顺序,你可以使用OrderedDict. 但是关于OrderedDicts,你应该记住一件事:

OrderedDict 仅在插入键时保持顺序。使用 kwargs 初始化时订单丢失。

来自Python docs:

OrderedDict 构造函数和update() 方法都接受关键字 参数,但它们的顺序丢失了,因为 Python 的函数调用 语义使用常规无序传入关键字参数 字典

你需要先创建一个OrderedDict实例,然后一个一个地添加key。

from collections import OrderedDict

def to_representation(self, pharmacy):
    ret = OrderedDict() # initialize on ordereddict

    # insert keys one by one in desired oreder
    ret['id'] = str(pharmacy.id)
    ret['name'] = pharmacy.name
    ret['email'] = pharmacy.email
    ret['mobile'] = pharmacy.mobile
    ret['address_line_1'] = pharmacy.address_line_1
    ret['address_line_2'] = pharmacy.address_line_2
    ret['city'] = pharmacy.city
    ret['state'] = pharmacy.state
    ret['zip'] = pharmacy.zip
    ret['created_by'] = pharmacy.created_by
    ret['created_on'] = pharmacy.created_on
    ret['last_updated_by'] = pharmacy.last_updated_by
    ret['license_number'] = pharmacy.license_number
    ret['bank_account'] = {
        'bank_name' = pharmacy.bank_account.bank_name
        'account_number' = pharmacy.bank_account.account_number
        'account_type' = pharmacy.bank_account.account_type
    }
    ret['last_updated_on'] = pharmacy.last_updated_on
    ret['is_email_verified'] = pharmacy.is_email_verified
    ret['is_mobile_verified'] = pharmacy.is_mobile_verified
    ret['is_active'] = pharmacy.is_active

    return ret

注意:另一个选项(推荐)是EmbeddedDocumentSerializer 用于bank_account 字段。这样您就不需要覆盖to_representation() 方法。

【讨论】:

  • 成功了!感谢 Rahul Gupta 的帮助 :) 非常感谢
【解决方案2】:

尝试在to_representation 中返回OrderedDict

def to_representation(self, pharmacy):
  return OrderedDict([('id', str(pharmacy.id),), ...])

代码中的 dict 对象本质上没有排序。假设框架在内部使用json.dump,您可以按照建议的here 使用有序对象来保持顺序。

【讨论】:

    猜你喜欢
    • 2021-10-11
    • 2019-08-20
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 2013-01-27
    • 1970-01-01
    相关资源
    最近更新 更多