Id вместо String при отображении поля внешнего ключа в DRF

Я пытаюсь вернуть имя поля "pricing", но все, что я получаю, это его внешний ключ id. Что я делаю не так? Любая информация по этому вопросу будет очень признательна. Я просмотрел здесь несколько похожих проблем, но не нашел ничего похожего на мою ситуацию.

class UserProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserProfile
        fields = (
            "assignedteams",
            "agent",
            "facility",
            "organisor",
            "avatar",
        )


class UserSubscriptionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Subscription
        fields = (
            "user",
            "pricing",
            "status",
        )


class UserSerializer(UserDetailsSerializer):

    profile = UserProfileSerializer(source="userprofile")
    subscription = UserSubscriptionSerializer(source="usersubscription")

    class Meta(UserDetailsSerializer.Meta):
        fields = UserDetailsSerializer.Meta.fields + ('profile', 'subscription',)

    def update(self, instance, validated_data):
        userprofile_serializer = self.fields['profile']
        userprofile_instance = instance.userprofile
        userprofile_data = validated_data.pop('userprofile', {})
    
        usersubscription_serializer = self.fields['subscription']
        usersubscription_instance = instance.usersubscription
        usersubscription_data = validated_data.pop('usersubscription', {})

        # update the userprofile fields
        userprofile_serializer.update(userprofile_instance, userprofile_data)
        usersubscription_serializer.update(usersubscription_instance, usersubscription_data)

        instance = super().update(instance, validated_data)
        return instance

Как вы говорите pricing вернул FK id, поэтому я предполагаю, что pricing колонка внутри Subscription model является FK к другой модели, давайте предположим, что это Pricing модель.

Вы можете создать сериализатор для Pricing и использовать его для UserSubscriptionSerializer, подобно тому, как вы создали UserProfileSerializer и UserSubscriptionSerializer для UserSerializer

Но использование непосредственно вложенного сериализатора создаст проблему при выполнении операции записи, поскольку, насколько я могу понять, вы принимаете pricing как значение FK, когда creating or updating

Для решения этой проблемы вы можете сделать несколько if/else в методе get_fields()

class UserSubscriptionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Subscription
        fields = (
            "user",
            "pricing",
            "status",
        )

    def get_fields(self):
        fields = super().get_fields()
        # make sure request is passed through context
        if self.context['request'] and self.context['request'].method == 'GET':
            fields['pricing']=PricingSerializer()
        return fields

Теперь вернемся к вопросу, поскольку вам нужен только pricing name, который, как я предполагаю, является столбцом на Pricing model. просто перепишите предыдущий код как

def get_fields(self):
    fields = super().get_fields()
    # make sure request is passed through context
    if self.context['request'] and self.context['request'].method == 'GET':
        fields['pricing'] = serializers.CharField(source='pricing.name', read_only=True)
    return fields

P.S: Я не тестировал этот код на своем компьютере

У вас есть 2 варианта решения этой проблемы.

option1:. Если вы хотите вернуть только название вашей модели ценообразования, вы можете использовать для этого SlugRelatedField.

Пример:

class UserSubscriptionSerializer(serializers.ModelSerializer):
    pricing = serializers.SlugRelatedField('name', readonly=True)

    class Meta:
        model = Subscription
        fields = (
            "user",
            "pricing",
            "status",
        )

Вариант2:. Если вы хотите вернуть объект Pricing, вы можете создать новый ModelSerializer для вашей модели Pricing и использовать его.

Пример:

class PricingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Pricing
        fields = ["id","name"]

class UserSubscriptionSerializer(serializers.ModelSerializer):
    pricing = PricingSerializer(readonly=True)

    class Meta:
        model = Subscription
        fields = (
            "user",
            "pricing",
            "status",
        )

Есть некоторые другие варианты, которые вы можете использовать, но вы должны объяснить больше о вашей проблеме, я помогу вам.

вы можете легко добавить новое представление поля или переопределить поле ценообразования, когда хотите представить данные поэтому в вашем сериализаторе добавьте следующий код

class UserSubscriptionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Subscription
        fields = (
            "user",
            "pricing",
            "status",
        )

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['pricing_name'] = instance.pricing.name # or replace the name with your pricing name field
        return data
Вернуться на верх