使用两个 "Sibling" 模型创建嵌套序列化程序
Creating a Nested Serializer with two "Sibling" Models
我正在尝试获得与此类似的 JSON 输出:
{
name: John Doe,
best_buy_price: 420,
best_sell_price: 69,
player_profile: {
tsn_link: https://a_link.com
}
playerlistingadvanced: { # This is where I'm having the issue
sales_minute: 7,
}
}
我有三个模型。 playerProfile
是“主要”模型,playerListing
和 playerListingAdvanced
通过一对一的关系连接到 playerProfile
。 playerPfofile
将有自己的端点,但我还想创建一个主要是列表和高级列表数据的端点(如上所示)。
这是 model.py 文件的精简版:
class PlayerProfile(models.Model):
card_id = models.CharField(max_length=120, unique=True, primary_key=True)
name = models.CharField(max_length=420, null=True)
tsn_link = models.CharField(max_length=420, null=True)
class PlayerListing(models.Model):
player_profile = models.OneToOneField(
PlayerProfile,
on_delete=models.CASCADE,
null=True)
name = models.CharField(max_length=420, null=True)
best_sell_price = models.IntegerField(null=True)
best_buy_price = models.IntegerField(null=True)
class PlayerListingAdvanced(models.Model):
player_profile = models.OneToOneField(
PlayerProfile,
on_delete=models.CASCADE,
null=True)
sales_minute = models.DecimalField(max_digits=1000, decimal_places=2, null=True)
这是 serializer.py 我已经尝试过,但还没有开始工作。
class PlayerListingAdvancedForNestingSerializer(serializers.ModelSerializer):
class Meta:
model = PlayerListingAdvanced
fields = (
'sales_minute',
'last_week_average_buy',
'last_week_average_sell',
)
class PlayerListingSerializer(serializers.ModelSerializer):
player_profile = PlayerProfileForListingSerializer() # works
playerlistingadvanced = PlayerListingAdvancedForNestingSerializer() #doesn't work
class Meta:
model = PlayerListing
fields = (
'name',
'best_sell_price',
'best_buy_price',
'playerlistingadvanced',
'player_profile'
)
我假设因为 playerListing 和 playerListingAdvanced 没有直接关系,所以我需要做一些其他事情来完成这项工作。有人能给我指出正确的方向吗?
您可以使用 SerializerMethodField。你的假设是正确的。试试这个:
class PlayerListingSerializer(serializers.ModelSerializer):
player_profile = PlayerProfileForListingSerializer()
playerlistingadvanced = serializers.SerializerMethodField()
class Meta:
model = PlayerListing
fields = (
'name',
'best_sell_price',
'best_buy_price',
'playerlistingadvanced',
'player_profile'
)
def get_playerlistingadvanced(self, obj: PlayerListing):
player_profile = obj.player_profile
if hasattr(player_profile, 'playerlistingadvanced'):
serializer = PlayerListingAdvancedForNestingSerializer(instance=player_profile.playerlistingadvanced)
return serializer.data
return None
我正在尝试获得与此类似的 JSON 输出:
{
name: John Doe,
best_buy_price: 420,
best_sell_price: 69,
player_profile: {
tsn_link: https://a_link.com
}
playerlistingadvanced: { # This is where I'm having the issue
sales_minute: 7,
}
}
我有三个模型。 playerProfile
是“主要”模型,playerListing
和 playerListingAdvanced
通过一对一的关系连接到 playerProfile
。 playerPfofile
将有自己的端点,但我还想创建一个主要是列表和高级列表数据的端点(如上所示)。
这是 model.py 文件的精简版:
class PlayerProfile(models.Model):
card_id = models.CharField(max_length=120, unique=True, primary_key=True)
name = models.CharField(max_length=420, null=True)
tsn_link = models.CharField(max_length=420, null=True)
class PlayerListing(models.Model):
player_profile = models.OneToOneField(
PlayerProfile,
on_delete=models.CASCADE,
null=True)
name = models.CharField(max_length=420, null=True)
best_sell_price = models.IntegerField(null=True)
best_buy_price = models.IntegerField(null=True)
class PlayerListingAdvanced(models.Model):
player_profile = models.OneToOneField(
PlayerProfile,
on_delete=models.CASCADE,
null=True)
sales_minute = models.DecimalField(max_digits=1000, decimal_places=2, null=True)
这是 serializer.py 我已经尝试过,但还没有开始工作。
class PlayerListingAdvancedForNestingSerializer(serializers.ModelSerializer):
class Meta:
model = PlayerListingAdvanced
fields = (
'sales_minute',
'last_week_average_buy',
'last_week_average_sell',
)
class PlayerListingSerializer(serializers.ModelSerializer):
player_profile = PlayerProfileForListingSerializer() # works
playerlistingadvanced = PlayerListingAdvancedForNestingSerializer() #doesn't work
class Meta:
model = PlayerListing
fields = (
'name',
'best_sell_price',
'best_buy_price',
'playerlistingadvanced',
'player_profile'
)
我假设因为 playerListing 和 playerListingAdvanced 没有直接关系,所以我需要做一些其他事情来完成这项工作。有人能给我指出正确的方向吗?
您可以使用 SerializerMethodField。你的假设是正确的。试试这个:
class PlayerListingSerializer(serializers.ModelSerializer):
player_profile = PlayerProfileForListingSerializer()
playerlistingadvanced = serializers.SerializerMethodField()
class Meta:
model = PlayerListing
fields = (
'name',
'best_sell_price',
'best_buy_price',
'playerlistingadvanced',
'player_profile'
)
def get_playerlistingadvanced(self, obj: PlayerListing):
player_profile = obj.player_profile
if hasattr(player_profile, 'playerlistingadvanced'):
serializer = PlayerListingAdvancedForNestingSerializer(instance=player_profile.playerlistingadvanced)
return serializer.data
return None