2016-06-18 7 views
3

Я использую Django Rest Framework (вместе с rest_framework_mongoengine) и переопределяя to_representation() моего сериализатора для отправки моего собственного объекта JSON. Все работает нормально, но порядок полей JSON перепутался. Скажите, пожалуйста, как изменить порядок/реструктурировать отправляемый объект JSON. Сериализатору выглядит следующим образом:Django Rest Framework - Как реструктурировать ответ 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": "[email protected]", 
     "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" 
    } 
] 

Я хочу, чтобы это было в том же порядке, обратном Dict из to_representation()

+2

Вы пытались использовать ['OrderedDict'] (https://docs.python.org/2/library/collections.html#collections.OrderedDict)? – gdlmx

+0

Это не сработало :( – heaVenShaker

+0

@heaVenShaker Есть ли какая-то особая причина, по которой вы переопределяете метод 'to_representation()'? Я не думаю, что вам нужно это сделать, поскольку вы просто обращаетесь к атрибутам объекта, который обычно возвращается DRF. –

ответ

3

Если вы хотите, чтобы поддерживать порядок ключей ответа, вы можете использовать OrderedDict. Но есть одна вещь, которую вы должны помнить о OrderedDicts:

OrderedDict поддерживает порядок только при вставки ключей. При попытке инициализации с помощью kwargs порядок теряется.

От Python docs:

Метода OrderedDict конструктора и update() как принять ключевые слово аргументов, но порядок их теряются, потому что вызов функции Пайтона семантику проход в ключевых аргументах с помощью обычного неупорядоченного словаря.

Необходимо сначала создать экземпляр OrderedDict, а затем добавить ключи один за другим.

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

+1

Это сработало! Спасибо Rahul Gupta за вашу помощь :) высоко оценил – heaVenShaker

+1

, посвященный обслуживанию ... @ Rahul –

3

Попробуйте вернуть OrderedDict в to_representation:

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

ди Объект ct в вашем коде не упорядочен по своей природе. Предположим, что каркас использует json.dump внутри, вы можете сохранить заказ, используя упорядоченный объект, как предлагается here.

+0

Нет, это не сработало :( – heaVenShaker