I am trying to display the url of a nested route that is 2 or more levels deep using the drf-nested-routes
module and the Django Rest Framework. I have no problems when it is only one level deep (i.e. getting the route with parent_lookup_kwargs
), but I receive the following error when I try to go deeper:
AttributeError at /en/api/v1.0/Sensors(1)/Datastreams(1)/Things 'RelatedManager' object has no attribute 'Sensors'
Here is some of the relevant serializer:
class ThingSerializer(SelectSerializerMixin,
ExpanderSerializerMixin,
serializers.ModelSerializer):
class Meta:
model = Thing
fields = ('@iot.id',
'@iot.selfLink',
'Locations@iot.navigationLink',
...
ThingSerializer._declared_fields["Datastreams@iot.navigationLink"] = \
NestedHyperlinkedIdentityField(
view_name='sensor-location-list',
parent_lookup_kwargs={'Sensors_pk':'Datastreams__Sensors__pk',
'nested_2_pk': 'Datastreams__pk'},
lookup_url_kwarg='nested_3_pk'
)
I am trying to show the url of a related field. Here are the available url routes:
en/ api/v1.0/ ^Sensors\((?P<Sensors_pk>[^/.]+)\)/Datastreams\((?P<nested_2_pk>[^/.]+)\)/Things\((?P<nested_3_pk>[^/.]+)\)/Locations$ [name='sensor-location-list']
en/ api/v1.0/ ^Sensors\((?P<Sensors_pk>[^/.]+)\)/Datastreams\((?P<nested_2_pk>[^/.]+)\)/Things\((?P<nested_3_pk>[^/.]+)\)/HistoricalLocations$ [name='sensor-historicallocation-list']
The routes are registered and I can access the nested resources no problem. It is only when I try to create a NestedHyperlinkedIdentityField
resource that fails.
NOTE,
I can get this to work if I use Many=True
in the NestedHyperlinkedIdentityField and change the source
field so it is not more than 1 parent deep:
NestedHyperlinkedIdentityField(
view_name='sensor-location-list',
many=True,
source='Datastreams',
parent_lookup_kwargs={'Sensors_pk': 'Sensors__pk',
'nested_2_pk': 'pk'},
lookup_url_kwarg='nested_3_pk'
)
But, this creates a ManyRelatedField
object and so the serialized output is:
"Locations@iot.navigationLink": [
"http://localhost:8000/en/api/v1.0/Sensors(1)/Datastreams(1)/Things(1)/Locations"
],
The desired output is:
"Locations@iot.navigationLink": "http://localhost:8000/en/api/v1.0/Sensors(1)/Datastreams(1)/Things(1)/Locations",
Any help will be much appreciated ^^.
edit:
It appears that it wont get the url when the model used in the serializer is a reverse relation of the parent. You can see this in the portion of models.py
:
class DataStream(models.Model):
....
Things = models.ForeignKey(Thing,
on_delete=models.SET_NULL,
null=True,
related_name="Datastreams"
Sensors = models.ForeignKey(Sensor,
on_delete=models.SET_NULL,
...