Reputation: 1955
Im trying to make a django-rest-framework
serializer where a related model can be linked by list instead of by detail
class Device(models.Model):
device_id = models.CharField(max_length=100)
class Log(models.Model):
device = models.ForeignKey(Device, related_name='logs')
class DeviceSerializer(serializers.HyperlinkedModelSerializer):
logs = serializers.HyperlinkedRelatedField(many=True, view_name='log-detail')
class Meta:
model = Device
fields = ('logs', 'url', 'device_id')
If I navigate to 'api/devices' is will return a list of devices like so:
[
{
"device_id": "12345"
"url": "http://localhost/api/devices/12345"
"logs": [
"http://localhost/api/logs/1",
"http://localhost/api/logs/2"
"http://localhost/api/logs/3"
"http://localhost/api/logs/4"
]
}
]
There can be many many logs. I don't want to write custom logic for pagination of logs inside the Device model, that should be handled by a Logs view.
I would like to have a result like this:
[
{
"device_id": "12345"
"url": "http://localhost/api/devices/12345"
"logs": [
"http://localhost/api/logs?device_id=12345"
]
}
]
And a api consumer can just navigate to the provided link to get the device logs.
It seems that serializer relations don't handle this use case. Can someone point me in the most framework idiomatic way to achieve this.
Upvotes: 0
Views: 50
Reputation: 893
There is one of the solutions:
Create a method (or property) in the Device model called, for example, get_logs_url
, that returned url for device logs:
class Device(models.Model):
...
get_logs_url(self):
# First parameter is the url name, 'device-logs' for example
return reverse('device-logs', kwargs={'device_id': self.device_id})
Add field logs_url
to DeviceSerializer
class DeviceSerializer(serializers.ModelSerializer):
...
logs_url = serializers.CharField(source='get_logs_url', read_only=True)
Then the result would be like this
[
{
"device_id": "12345"
"logs": "/api/logs?device_id=12345"
}
]
If you want absolute url in result then your serializer should look something like this
class DeviceSerializer(serializers.ModelSerializer):
logs_url = serializer.SerializerMethodField()
def get_logs_url(self, device):
return self.context['request'].build_absolute_uri(device.get_logs_url())
Then the result would be like this
[
{
"device_id": "12345"
"logs": "http://localhost/api/logs?device_id=12345"
}
]
Upvotes: 1