python - tutorial - partial update django rest framework
AdiciĆ³n de datos adicionales a los resultados de Django Rest Framework para todo el conjunto de resultados (3)
Estoy usando Django Rest Framework y necesito agregar datos adicionales a un conjunto de resultados. Específicamente, donde normalmente tendrías:
{
"count": 45,
"next": "http://localhost:8000/foo/bar?page=2",
"previous": null,
"results": [
{...}
]
}
Me gustaría agregar cuentas adicionales como así:
{
"count": 45,
"10_mi_count": 10,
"20_mi_count": 30,
"30_mi_count": 45,
"next": "http://localhost:8000/foo/bar?page=2",
"previous": null,
"results": [
{...}
]
}
Los conteos adicionales en este ejemplo son solo cuántos de los objetos tienen una distancia de campo con un valor menor que las millas descritas en la clave.
Mi problema es que no tengo idea de cuál es el mejor lugar para extender e insertar este comportamiento.
Idealmente, me gustaría que esto funcionara ya sea que los resultados estén paginados o no, sin hacer suposiciones.
Lo que realmente busco aquí es un guiño en la dirección correcta (y por qué ese es el lugar correcto para hacerlo).
He revisado los documentos y no puedo encontrar nada que describa cómo agregar cosas como esta, pero estaría más que feliz de estar equivocado en ese aspecto.
Al final, acabo de crear un serializador de paginación personalizado con un campo como el siguiente:
class DistanceCountField(serializers.Field):
def to_native(self, value):
try:
distance_counts = {
''1_mile'': self._count_lte_miles(value, 1),
''5_mile'': self._count_lte_miles(value, 5),
''10_mile'': self._count_lte_miles(value, 10),
''20_mile'': self._count_lte_miles(value, 20),
}
except FieldError:
distance_counts = None
return distance_counts
def _count_lte_miles(self, value, miles):
meters = miles * 1609.344
return value.filter(distance__lte=meters).count()
class PaginatedCountSerializer(pagination.PaginationSerializer):
distance_counts = DistanceCountField(source=''paginator.object_list'')
class Meta:
# Class omitted, just a standard model serializer
object_serializer_class = MyModelSerializer
También agregué una anotación de distancia a cada objeto en el queryset para que funcione el filtrado.
Use SerializerMethodField como se menciona en esta solution .
Se puede usar para agregar cualquier tipo de datos a la representación serializada de su objeto. ( SerializerMethodField )
Ejemplo de la documentación:
from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
days_since_joined = serializers.SerializerMethodField()
class Meta:
model = User
def get_days_since_joined(self, obj):
return (now() - obj.date_joined).days
Ya que parece estar usando una de las ListViews del Marco de Rest, puede reemplazar el método list () en su clase y establecer nuevos valores en los datos resultantes, como esto:
def list(self, request, *args, **kwargs):
response = super().list(request, args, kwargs)
# Add data to response.data Example for your object:
response.data[''10_mi_count''] = 10 # Or wherever you get this values from
response.data[''20_mi_count''] = 30
response.data[''30_mi_count''] = 45
return response
Tenga en cuenta que su clase debe heredar ListModelMixin directamente oa través de un GenericView de la API del Marco Rest ( http://www.django-rest-framework.org/api-guide/generic-views#listmodelmixin ). Realmente no sé si es la forma correcta de hacer esto, pero es una solución rápida.
¡Espero eso ayude!