Django rest framework изменить первичный ключ, чтобы использовать поле unqiue

У меня есть модель, которая называется GameProfile, которая является отношением "один к одному" с моделью User. Я использовал HyperlinkedModelSerializer во всем моем дизайне.

Для GameProfile поле пользователя должно быть основным ключом для запроса, оно уникально, но я не настроил его как первичный ключ. Есть ли способ изменить поведение по умолчанию для django serializer, чтобы указать на user__id в качестве первичного ключа и всегда использовать его для получения профиля в подробном представлении?

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

пожалуйста, сообщите, спасибо заранее:)

Ответ 1

Предполагая, что ваша модель GameProfile выглядит следующим образом:

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

Сериализатор будет:

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

    class Meta:
        model = GameProfile

Установите атрибут .lookup_field в представлении правильно:

    lookup_field = 'user_id'

Url будет:

/gameprofile/<user_id>

Ответ 2

Чтобы заставить URL-адреса работать, вам может потребоваться добавить lookup_field в ViewSet, а не только в сериализатор. Таким образом, у вас будет:

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

В этом случае lookup_field использует ноту с двойным подчеркиванием, а не точечную нотацию (точки не будут работать в регулярных выражениях в шаблонах URL). Мне не удалось найти решение, предложенное @almalki и @patsweet для работы; в соответствии с документацией для сериализаторов: "Значение этой опции [ lookup_field] должно соответствовать как kwarg в URL conf, так и с полем на модели", поэтому возможно, что он не работает с RelatedFields.

Ответ 3

Если я правильно понимаю ваш вопрос, вам нужна структура URL-адреса:

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

Если это так, вы должны проверить вариант lookup_field. Ссылка

Класс Serializer будет выглядеть примерно так:

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'