Como fazer, em sua API, para exibir os dados de algum relacionamento? Essa é a pergunta que me fiz há um tempo atrás. Imagine que você tenha uma API que retorne Ordens de Serviço (ORDENS) e que essas ORDENS possuem vários apontamentos de hora, que chamaremos de LOG. Como fazer para que, em cada Ordem, sejam retornados todos os Logs?
O que queremos, é exibir algo assim:

PRIMEIRO PASSO: MODELS
class MaintenanceOrder(models.Model):
order_code = models.CharField(max_length=12, null=True)
note_code = models.CharField(max_length=12, null=True)
equipment = models.CharField(max_length=18, null=True)
locale = models.CharField(max_length=30, null=True)
short_description = models.CharField(max_length=40, null=False)
description = models.TextField(null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.order_code
class Meta:
managed = True
class MaintenanceLog(models.Model):
maintenance_order = models.ForeignKey(MaintenanceOrder, on_delete=models.DO_NOTHING)
start_time = models.DateTimeField()
stop_time = models.DateTimeField(null=True)
description = models.TextField(null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.description
class Meta:
managed = True
SEGUNDO PASSO: SERIALIZERS
Você deverá criar agora dois Serializers em um arquivo chamado serializers.py.
class MaintenanceLogSerializer(serializers.ModelSerializer):
class Meta:
model = MaintenanceLog
fields = '__all__'
class MaintenanceOrderSerializer(serializers.ModelSerializer):
status_code = serializers.IntegerField(source='status.status_code', read_only=True)
order_log = MaintenanceLogSerializer(source='maintenancelog_set', many=True, read_only=True)
class Meta:
model = MaintenanceOrder
fields = ('id', 'order_code', 'note_code',
'equipment', 'locale',
'short_description', 'description',
'created_at', 'updated_at',
'order_log')
O segredo está na classe MaintenanceOrderSerializer, na variável order_log. Nessa variável, setamos o MaintenanceLogSerializer e setamos que a fonte dele é uma chave estrangeira.
Nesse timo de relacionamento (1 x N), temos que especificar todos os campos que queremos exibir. Não podemos setar ‘__all__’.
TERCEIRO PASSO: VIEW
@api_view(['GET'])
def orders(request):
try:
orders = MaintenanceOrder.objects.all()
results = MaintenanceOrderSerializer(orders, many=True).data
return Response({
'response': 'success',
'data': results
}, status=status.HTTP_200_OK)
except MaintenanceOrder.DoesNotExist:
return Response(data={'response': 'null'}, status=status.HTTP_204_NO_CONTENT)
QUARTO PASSO: URL (rotas)
Agora basta criar sua rota. Veja um exemplo:
path('api/v1/orders', api.orders, name='meuapp.orders'), ...
RESULTADO
O resultado deverá ser algo como:
{
{
"id": 86,
"order_code": "000310016530",
"note_code": "",
"equipment": "000000000050002836",
"locale": "CF10-431-ND",
"short_description": "Bomba parada",
"description": null,
"created_at": "2018-09-17T13:40:10.697260",
"updated_at": "2018-09-17T13:40:10.697277",
"order_log": []
},
{
"id": 100,
"order_code": null,
"note_code": null,
"equipment": "86754",
"locale": "MP10-642-INF",
"short_description": "Mais um teste!",
"description": "",
"created_at": "2018-09-18T15:45:57.172669",
"updated_at": "2018-09-18T15:46:17.445052",
"order_log": [
{
"id": 41,
"start_time": "2018-09-18T15:45:59.214199",
"stop_time": "2018-09-18T15:46:03.627028",
"description": "Ordem pausada.",
"created_at": "2018-09-18T15:45:59.214911",
"updated_at": "2018-09-18T15:46:03.628129",
"maintenance_order": 100,
},
{
"id": 42,
"start_time": "2018-09-18T15:46:06.134436",
"stop_time": "2018-09-18T15:46:17.459454",
"description": "Ordem pausada.",
"created_at": "2018-09-18T15:46:06.135495",
"updated_at": "2018-09-18T15:46:17.460069",
"maintenance_order": 100
}
]
}
}
Espero que tenha ajudado como fui ajudado.
Mais detalhes podem ser vistos nessa dúvida que havia lançado no StackOverflow.
