custom URLs using django rest framework

2019-03-21 00:21发布

问题:

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:

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')


回答2:

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')