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.