python - tutorial - extra kwargs django rest
Incluir intermediario(a través del modelo) en las respuestas en Django Rest Framework (2)
Tengo una pregunta sobre el manejo de m2m / a través de modelos y su presentación en el marco de descanso django. Tomemos un ejemplo clásico:
models.py:
from django.db import models
class Member(models.Model):
name = models.CharField(max_length = 20)
groups = models.ManyToManyField(''Group'', through = ''Membership'')
class Group(models.Model):
name = models.CharField(max_length = 20)
class Membership(models.Model):
member = models.ForeignKey(''Member'')
group = models.ForeignKey(''Group'')
join_date = models.DateTimeField()
serializers.py:
imports...
class MemberSerializer(ModelSerializer):
class Meta:
model = Member
class GroupSerializer(ModelSerializer):
class Meta:
model = Group
views.py:
imports...
class MemberViewSet(ModelViewSet):
queryset = Member.objects.all()
serializer_class = MemberSerializer
class GroupViewSet(ModelViewSet):
queryset = Group.objects.all()
serializer_class = GroupSerializer
Cuando OBTENGO una instancia de Miembro, recibo con éxito todos los campos de los miembros y también sus grupos; sin embargo, solo obtengo los detalles de los grupos, sin detalles adicionales que provienen del modelo de Membresía.
En otras palabras, espero recibir:
{
''id'' : 2,
''name'' : ''some member'',
''groups'' : [
{
''id'' : 55,
''name'' : ''group 1''
''join_date'' : 34151564
},
{
''id'' : 56,
''name'' : ''group 2''
''join_date'' : 11200299
}
]
}
Tenga en cuenta el join_date .
He intentado tantas soluciones, incluida, por supuesto, la página oficial de Django Rest-Framework al respecto y nadie parece dar una respuesta clara al respecto. ¿Qué debo hacer para incluir estos campos adicionales? Lo encontré más directo con django-tastypie pero tuve algunos otros problemas y prefiero rest-framework.
Estaba enfrentando este problema y mi solución (usando DRF 3.6) era usar SerializerMethodField en el objeto y consultar explícitamente la tabla de Membresía como sigue:
class MembershipSerializer(serializers.ModelSerializer):
"""Used as a nested serializer by MemberSerializer"""
class Meta:
model = Membership
fields = (''id'',''group'',''join_date'')
class MemberSerializer(serializers.ModelSerializer):
groups = serializers.SerializerMethodField()
class Meta:
model = Member
fields = (''id'',''name'',''groups'')
def get_groups(self, obj):
"obj is a Member instance. Returns list of dicts"""
qset = Membership.objects.filter(member=obj)
return [MembershipSerializer(m).data for m in qset]
Esto devolverá una lista de dicts para la clave de grupos donde cada dict se serializa desde MembershipSerializer. Para hacerlo modificable, puede definir su propio método de creación / actualización dentro de MemberSerializer donde iterará sobre los datos de entrada y creará o actualizará explícitamente las instancias del modelo de Membresía.
Qué tal si.....
En su MemberSerializer, defina un campo en él como:
groups = MembershipSerializer(source=''membership_set'', many=True)
y luego en su serializador de membresía puede crear esto:
class MembershipSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field(source=''group.id'')
name = serializers.Field(source=''group.name'')
class Meta:
model = Membership
fields = (''id'', ''name'', ''join_date'', )
Eso tiene el efecto general de crear un valor serializado, grupos, que tiene como fuente la membresía que desea, y luego utiliza un serializador personalizado para extraer los bits que desea mostrar.
EDITAR: como se comentó por @bryanph, serializers.field
se renombró a serializers.ReadOnlyField
en DRF 3.0, por lo que debería leer:
class MembershipSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.ReadOnlyField(source=''group.id'')
name = serializers.ReadOnlyField(source=''group.name'')
class Meta:
model = Membership
fields = (''id'', ''name'', ''join_date'', )
para cualquier implementación moderna