Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django rest framework change primary key to use a unqiue field

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

like image 389
Mo J. Mughrabi Avatar asked Mar 10 '14 14:03

Mo J. Mughrabi


3 Answers

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>
like image 58
almalki Avatar answered Oct 12 '22 07:10

almalki


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.

like image 44
Avril Avatar answered Oct 12 '22 07:10

Avril


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'
like image 35
patsweet Avatar answered Oct 12 '22 07:10

patsweet