6

Problem :

I am getting an error like this .

ImproperlyConfigured at /api/users/

Could not resolve URL for hyperlinked relationship using view name "user-detail". You may have failed to include the related model in your API, or incorrectly configured the lookup_field attribute on this field.

I read this post but it didn't work.

serializers.py

class UserSerializer(serializers.ModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name='user-detail',
                                               lookup_field='profile')

    class Meta:
        model = User
        fields = ('id', 'username', 'first_name', 'last_name', 'url')


class UserProfileSerializer(serializers.ModelSerializer):
    user = serializers.ReadOnlyField(source='user.username')

    class Meta:
        model = UserProfile
        fields = "__all__"
        # user = serializers.ReadOnlyField(source='owner.username')

    def create(self, validated_data):
        pass

    def update(self, instance, validated_data):
        pass

urls.py

user_profile_list = UserProfileViewSet.as_view({
    'get': 'list',
    'post': 'create'
})
user_profile_detail = UserProfileViewSet.as_view({
    'get': 'retrieve',
    'put': 'update',
    'patch': 'partial_update',
    'delete': 'destroy'
})
user_list = UserViewSet.as_view({
    'get': 'list'
})
user_detail = UserViewSet.as_view({
    'get': 'retrieve'
})
user_profiles_detail = UserViewSet.as_view({
    'get': 'profile'
})

router = DefaultRouter()
router.register(r'userprofiles', views.UserProfileViewSet)
router.register(r'users', views.UserViewSet)

urlpatterns = [
    url(r'^', include(router.urls))
]

views.py

class UserProfileViewSet(viewsets.ModelViewSet):
    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions.
    """
    queryset = UserProfile.objects.all()
    serializer_class = UserProfileSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                          IsOwnerOrReadOnly,)
    pagination_class = LimitTenPagination

    @detail_route(renderer_classes=[renderers.JSONRenderer])
    def perform_create(self, serializer):
        serializer.save(user=self.request.user)


class UserViewSet(viewsets.ReadOnlyModelViewSet):
    """
    This viewset automatically provides `list` and `detail` actions
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

Snippet from my models.py

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')

What I tried :

I tried changing user-detail to api:user-detail ( yes api namespace do exist in the main urls.py file )

4
  • I understand that what you want is to have a field in the User serializer pointing to the URL of its profile, right? Commented Jan 20, 2018 at 21:12
  • Are you trying to have url point to the user detail view or the user profile detail view? Commented Jan 20, 2018 at 21:12
  • 1
    @JessamynSmith I am trying to get it to user-detail, that's why I have chosen the model as User and not UserProfile Commented Jan 20, 2018 at 21:15
  • 1
    @dukebody yes, that's it Commented Jan 20, 2018 at 21:16

3 Answers 3

9
  1. Looking at the docs, I believe you have to use HyperLinkedRelatedField. Also, see this related SO post.

  2. You are confusing arguments in your serializer field definition. What I believe should be:

    class UserSerializer(serializers.ModelSerializer):
        url = serializers.HyperlinkedRelatedField(view_name='api:userprofile-detail',
                                                  source='profile')
    

Edit :

Added namespace api

Sign up to request clarification or add additional context in comments.

2 Comments

I found that this worked only if I named the field the same as in the model, e.g.: profile = serializers.HyperlinkedRelatedField(read_only=True, view_name='userprofiles-detail')
@JessamynSmith yes that's why namespace needs to be added
1

Remove lookup_filed attribute from your HyperlinkedIdentityField since you do not need it.

Hence your serializer class should instead look like below:

class UserSerializer(serializers.ModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name='user-detail', source='profile',)

    class Meta:
        model = User
        fields = ('id', 'username', 'first_name', 'last_name', 'url')

The attribute lookup_filed is only needed when referring to a model class with relationship-field/attribute used as a primary key instead of the default autoincrement. For example, it would have been relevant to use it if your model class looked like below:

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile', primary_key=True)

Comments

0

If you're extending the GenericViewSet and ListModelMixin classes, and have the same error when adding the url field in the list view, it's because you're not defining the detail view. Be sure you're extending the RetrieveModelMixin mixin:

class UserViewSet (mixins.ListModelMixin,
                   mixins.RetrieveModelMixin,
                   viewsets.GenericViewSet):

Credits to an answer from Rowinson Gallego

Comments

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.