Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

custom URLs using django rest framework

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?

like image 890
Rajesh Chamarthi Avatar asked Aug 24 '15 12:08

Rajesh Chamarthi


People also ask

How do I create a custom exception in Django REST framework?

Custom exception handlingThe exception handler function should either return a Response object, or return None if the exception cannot be handled. If the handler returns None then the exception will be re-raised and Django will return a standard HTTP 500 'server error' response.

Is Django GOOD FOR REST API?

Django REST framework (DRF) is a powerful and flexible toolkit for building Web APIs. Its main benefit is that it makes serialization much easier. Django REST framework is based on Django's class-based views, so it's an excellent option if you're familiar with Django.

What is difference between APIView and Viewset?

APIView allow us to define functions that match standard HTTP methods like GET, POST, PUT, PATCH, etc. Viewsets allow us to define functions that match to common API object actions like : LIST, CREATE, RETRIEVE, UPDATE, etc.

What is Viewset Django?

A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as .get() or .post() , and instead provides actions such as .list() and .create() .


2 Answers

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')
like image 182
Rajesh Chamarthi Avatar answered Sep 30 '22 14:09

Rajesh Chamarthi


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')
like image 28
Seenu S Avatar answered Sep 30 '22 14:09

Seenu S