7

I am trying to use the django rest framework to expose my models as APIs.

serializers

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User

viewset

class UserViewSet(viewsets.ModelViewSet):
    """
    API end point for User details and list
    """
    serializer_class = UserSerializer
    queryset = User.objects.all()

routers

router.register(r'users',views.UserViewSet)

While this exposes /users/ and users/, I want my URLs to include a user-slug as well, something like /users/1/xyz-user-name.

Has anyone solved this problem? Does this need changes in both the viewset and router code or is it something that can be configured only in the router code? MY "slug" isn't really used for determining url routing, it is only for URL readability.

Any pointers?

1
  • for getting the details of the UserViewSet endpoint. or Post. Commented Aug 25, 2015 at 9:01

2 Answers 2

8

I was able to get this to work by using the approach posted here.

django-rest-framework HyperlinkedIdentityField with multiple lookup args

The second error I was receiving was becuase I was including the url definition inside the meta section. It should be before the meta section instead. I also had to specify the lookup field in the viewset code. Here are the relevant parts of my code.

urls.py

from user.views import UserViewSet
user_list = UserViewSet.as_view({'get':'list'})
user_detail = UserViewSet.as_view({'get':'retrieve'})

urlpatterns= [
    url(r'^users/$', user_list, name='user-list'),
    url(r'^user/(?P<id>\d+)/(?P<slug>[-\w\d]+)/$', user_detail, name='user-detail'),
    url(r'^api-auth/', include('rest_framework.urls',namespace = 'rest_framework'))
]

views.py:

class UserViewSet(viewsets.ModelViewSet):
    """
    API end point for user details and user list
    """
    lookup_field = 'id'
    serializer_class = UserSerializer
    queryset = user.objects.all()

serializers.py

class UserSerializer(serializers.HyperlinkedModelSerializer):
    url = ParameterisedHyperlinkedIdentityField(view_name='user-detail', lookup_fields=(('id', 'id'), ('slug', 'slug')), read_only=True)

    class Meta:
        model = user
        fields = ('url','name','cover_photo')
Sign up to request clarification or add additional context in comments.

1 Comment

When I use as_view({'get':'retrieve'}) in django 2.2 I get error.
4

You should set the lookup_field property in the serializers and viewsets.

In the serializers.py:

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ('url', 'username', 'email', 'user_slug')
        lookup_field = 'user_slug'
        extra_kwargs = {
            'url': {'lookup_field': 'user_slug'}
        }

In the viewsets.py:

class UserViewSet(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    queryset = User.objects.all()
    lookup_field = ('user_slug')

5 Comments

Thanks.. But My requirement is still to lookup by primary key, but the final url should have the slug as well.
Pass the primary key and slug feild both.
Tried it and I get "__init__() got an unexpected keyword argument 'id'"
Thanks Seenu. The lookupfield helped with showing the detail view, but for the links to have id and url, I had to create a new class. I posted an answer with the details.
Can we add multiple lookup fields, if I have a table called articles? can I add something like this: lookup_field = ('id','slug')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.