Eu tenho uma pergunta sobre como lidar com modelos m2m / through e sua apresentação no framework django rest. Vamos dar um exemplo clássico:
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
Ao OBTER uma instância de Membro, recebo com sucesso todos os campos de Membros e também seus grupos - porém, só recebo os detalhes dos grupos, sem detalhes extras que vêm do modelo de Membros.
Em outras palavras, espero receber:
{
'id' : 2,
'name' : 'some member',
'groups' : [
{
'id' : 55,
'name' : 'group 1'
'join_date' : 34151564
},
{
'id' : 56,
'name' : 'group 2'
'join_date' : 11200299
}
]
}
Observe o join_date .
Eu tentei tantas soluções, incluindo, é claro, a página oficial do Django Rest-Framework sobre isso e ninguém parece dar uma resposta clara e adequada sobre isso - o que eu preciso fazer para incluir esses campos extras? Achei mais direto com django-tastypie, mas tive alguns outros problemas e prefiro rest-framework.
Respostas:
E se.....
Em seu MemberSerializer, defina um campo como:
e, em seu serializador de associação, você pode criar este:
Isso tem o efeito geral de criar um valor serializado, grupos, que tem como origem a associação que você deseja e, em seguida, usa um serializador personalizado para retirar os bits que deseja exibir.
EDITAR: conforme comentado por @bryanph,
serializers.field
foi renomeado paraserializers.ReadOnlyField
no DRF 3.0, então deve ser:para qualquer implementação moderna
fonte
membership_set
é o nome relacionado padrão para Membro -> AssociaçãoEu estava enfrentando esse problema e minha solução (usando DRF 3.6) foi usar SerializerMethodField no objeto e consultar explicitamente a tabela de membros da seguinte maneira:
Isso retornará uma lista de dicts para a chave de grupos, onde cada dict é serializado a partir do MembershipSerializer. Para torná-lo gravável, você pode definir seu próprio método de criação / atualização dentro do MemberSerializer, onde você itera sobre os dados de entrada e cria ou atualiza explicitamente as instâncias do modelo de associação.
fonte
NOTA: Como um engenheiro de software, adoro usar arquiteturas e trabalhei profundamente na Abordagem em camadas para o desenvolvimento, portanto, responderei com respeito às camadas.
Pelo que entendi o problema, aqui está a solução models.py
serializers.py
CustomModels.py
BusinessLogic.py
Tecnicamente, você teria que passar a Solicitação para DataAccessLayer, que retornaria os Objetos Filtrados da Camada de Acesso a Dados, mas como tenho que responder à pergunta de maneira rápida, ajustei o código na camada de lógica de negócios!
fonte