[Fixed]-Django REST: How to use Router in application level urls.py?

27👍

The problem here is that you are using Django REST Framework with a namespace. Many components do not work well with them, which doesn’t mean they can’t be used, so you need to work around the issues by doing a lot of manual work. The main problem is with hyperlinked relations (Hyperlinked*Fields), because they have to reverse views, and that requires that the namespace is specified.

The first place to start at is the router level, which doesn’t currently support namespaces. This is only an issue for the DefaultRouter, as it will build out the index page that contains a list of reversed urls, which will trigger errors right away. This has been fixed in the upcoming release, but for now you’re stuck without it. At best (DRF 3.0+), the index page will be completely empty (or point to incorrect urls), in the worst case scenario (DRF 2.x) it will always trigger an internal server error.

The second place to look at is the serializer fields. By default, the HyperlinkedModelSerializer will automatically generate HyperlinkedRelatedField and HyperlinkedIdentityField fields with non-namespaced urls. When you are using namespaces, you have to override all of these automatically generated fields. This generally means you are better off just not using a HyperlinkedModelSerializer, and instead controlling the output with a ModelSerializer.

The first (and easiest) thing to fix is the url field that is automatically generated for all objects. This is automatically generated with view_name set to the detail page (thread-detail in this case), without a namespace. You are going to need to override the view_name and include the namespace in front of it (so scradeweb:thread-detail in this case).

class ThreadSerializer(serializers.ModelSerializer):
    url = serializers.HyperlinkedIdentityField(
        view_name="scradeweb:thread-detail",
    )

You are also going to need to override all of the automatically generated related fields. This is slightly more difficult for writable fields, but I would always recommend looking at repr(MySerializer()) in those cases to see the arguments for the automatically generated fields. For the case of read-only fields, it’s a matter of just copying over the default arguments and changing the view_name again.

class ThreadSerializer(serializers.ModelSerializer):
    posts = serializers.HyperlinkedRelatedField(
        many=True,
        read_only=True,
        view_name='scradeweb:post-detail',
    )

This will need to be done for all fields, and it doesn’t look like Django REST Framework will be adding the ability to do it automatically in the near future. While this will not be enjoyable at first, it will give you a great opportunity to appreciate everything DRF previously did for you automatically.

1👍

I have had the same kind of issue and fix it just change the "HyperlinkedModelSerializer" to "ModelSerializer".
I am just following the rest framework tutorial and got stucked in this part

class TodoSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model =  TodoList
        fields =  '__all__'

to:

class TodoSerializer(serializers.ModelSerializer):
    class Meta:
        model =  TodoList
        fields =  '__all__'

Leave a comment