0

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,
                                ...
iosefa
  • 1
  • 1
  • 1
  • Can you confirm that your object name is `Datastreams` and it's attribute name is `Sensors` ? These must be field name and not model Class name – Umair Mohammad Dec 18 '18 at 05:05
  • @MohammadUmair `Datastreams` is the related name of a Foreign Key to the `Thing` model class. And `Sensors` is a field in the `DataStream` model class. I'm updating the post to include a portion of `models.py` – iosefa Dec 18 '18 at 08:37
  • I should also say that I can access the nested routes no problem. i.e. I can get serialized data from `http://localhost:8000/en/api/v1.0/Sensors(1)/Datastreams(1)/Things(1)/Locations`. I'm only having problems with displaying the url as a field using `NestedHyperlinkedIdentityField` – iosefa Dec 18 '18 at 08:57
  • I edited the question and title to reflect that this is only an issue when the model of the serializer is a reverse relation of the parent. – iosefa Dec 18 '18 at 23:15

0 Answers0