django rest framework change primary key to use a

2020-06-01 07:12发布

I have a model which is called GameProfile, which is a one to one relation with User model. I used HyperlinkedModelSerializer across all my design.

For the GameProfile, the user field is suppose to be the primary key for querying, it is unique but I did not set it up as a primary key. Is there a way to change the default behavior of django serializer to point to user__id as the primary key and always use it for retreiving the profile in the detail view?

class GameProfileSerializer(serializers.HyperlinkedModelSerializer):
    """ 
    """
    user_pk = serializers.Field(source='user.id')

    class Meta:
        model = GameProfile


class GameProfileViewSet(viewsets.ModelViewSet):
    """
    """
    queryset = GameProfile.objects.all()
    serializer_class = GameProfileSerializer

    def get_queryset(self):
        """ get_queryset
        """
        queryset = super(GameProfileViewSet, self).get_queryset()
        if not queryset.exists():
            raise Http404
        if self.request.user.is_authenticated() and not self.request.user.is_superuser:
            return queryset.filter(user=self.request.user)
        return queryset

please advise, thanks in advance:)

3条回答
一纸荒年 Trace。
2楼-- · 2020-06-01 07:54

Assuming your GameProfile model looks like:

class GameProfile(models.Model)
    user = models.OneToOneField('User')

The serializer will be:

class GameProfileSerializer(serializers.HyperlinkedModelSerializer):
    user_id = serializers.Field(source='user.id')

    class Meta:
        model = GameProfile

Set the .lookup_field attribute on the view correctly:

    lookup_field = 'user_id'

Url will be:

/gameprofile/<user_id>
查看更多
倾城 Initia
3楼-- · 2020-06-01 07:55

If I'm understanding your question correctly, you want a url structure like so:

/api/<GameProfile-resource>/<user-pk>

If that is the case, you should checkout the lookup_field option. Link

You're Serializer class would look something like:

class GameProfileSerializer(serializers.HyperlinkedModelSerializer):
    """ 
    """
    user_pk = serializers.Field(source='user.id')

    class Meta:
        model = GameProfile
        lookup_field = 'user_pk'  # Might have to use 'user__id'
查看更多
放我归山
4楼-- · 2020-06-01 07:56

In order to get the URLs to work, you might need to add lookup_field on the ViewSet, not just on the serializer. So you would have:

class GameProfileViewSet(viewsets.ModelViewSet):
    queryset = GameProfile.objects.all()
    serializer_class = GameProfileSerializer
    lookup_field = 'user__id'

In this case the lookup_field uses the double-underscore notation rather than the dot notation (dots won't work in the regular expressions in the URL patterns). I was unable to get the solution proposed by @almalki and @patsweet to work; according to the documentation on serializers, "The value of this option [lookup_field] should correspond both with a kwarg in the URL conf, and with a field on the model", so it's possible that it doesn't work with RelatedFields.

查看更多
登录 后发表回答