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