Devuelva la lista de objetos como diccionario con claves como la identificación de objetos con django rest framerwork

Actualmente, tengo un ListAPIView que devuelve una lista de diccionarios de objetos:

[ { id: 1, ...}, { id: 2, ...}, ... ] 

Me gustaría cambiarlo para que se formatee como un diccionario con el ID como la clave:

 { "1": { id: 1, ...}, "2": { id: 2, ...}, ... } 

¿Cómo personalizo la salida de esta manera utilizando Django Rest Framework? Actualmente estoy haciendo el re-formato del lado del cliente, pero me gustaría hacerlo del lado del servidor.

Creo que puedes implementar la función to_representation en tu Serializador.

 class MySerializer(serializers.Serializer): id = serializers.ReadOnlyField() field1 = serializers.ReadOnlyField() field2 = serializers.ReadOnlyField() def to_representation(self, data): res = super(MySerializer, self).to_representation(data) return {res['id']: res} # or you can fetch the id by data directly # return {str(data.id): res} 

Puede atravesar cada elemento y, con un dictado de comprensión, cree el diccionario que desee. Por ejemplo:

 >>> l = [{ "id": 1, "x": 4}, { "id": 2, "x": 3}] >>> {v["id"]: v for v in l} {1: {'x': 4, 'id': 1}, 2: {'x': 3, 'id': 2}} 

EDITAR: versión actual disponible en un proyecto Github y PYPI ( pip install drf-keyed-list )

Aquí hay una clase de propósito general que es bidireccional (frente a la implementación de solo lectura anterior):

 class KeyedListSerializer(ListSerializer): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) meta = getattr(self.child, 'Meta', None) assert hasattr(meta, 'keyed_list_serializer_field'), \ "Must provide a field name at keyed_list_serializer_field when using KeyedListSerializer" self._keyed_field = meta.keyed_list_serializer_field def to_internal_value(self, data): # syntax is py3 only data = [{**v, **{self._keyed_field: k}} for k, v in data.items()] return super().to_internal_value(data) def to_representation(self, data): response = super().to_representation(data) return {v.pop(self._keyed_field): v for v response} 

Para Py2, debe hacer que las super llamadas sean explícitas y reemplazar el constructor del diccionario indicado. Lo usas asignándolo a tu list_serializer_class y seleccionando un keyed_list_serializer_field (es decir, el campo usado como la tecla dict):

 class MySerializer(ModelSerializer): class Meta: list_serializer_class = KeyedListSerializer keyed_list_serializer_field = 'id' 

El campo keyed_list_serializer_field debe contener valores únicos; la implementación anterior no se comprueba.