首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在django rest框架中用不同的序列化器类序列化每个外键对象

如何在django rest框架中用不同的序列化器类序列化每个外键对象
EN

Stack Overflow用户
提问于 2021-01-12 09:57:06
回答 1查看 1.5K关注 0票数 0

因此,我想知道在django rest框架中是否可以用不同的序列化程序序列化每个外键对象。

我的意思是:

我的模特们就像

代码语言:javascript
复制
class KingdomModel(models.Model):
    kingdom_name = models.CharField(max_length=32)
    owner = models.OneToOneField(User, on_delete=models.CASCADE)
    faction = models.CharField(max_length=10)
    

class CityModel(models.Model):
    kingdom = models.ForeignKey(KingdomModel, on_delete=models.CASCADE, related_name="cities")
    city_name = models.CharField(max_length=32)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    """
    ... other fields aswell
    """


class ArmyModel(models.Model):
    home_city = models.ForeignKey(CityModel, on_delete=models.CASCADE, null=True, related_name="own_troops")
    current_city = models.ForeignKey(CityModel, on_delete=models.CASCADE, null=True, related_name="all_troops", blank=True)
    status = models.CharField(max_length=32)
    action_done_time = models.DateTimeField(default=None, null=True, blank=True)
    target_city = models.ForeignKey(CityModel, on_delete=models.CASCADE, null=True, related_name="incoming_troops", default=None, blank=True)

    # Shared troops
    settlers = models.IntegerField(default=0)

    # Gaul troops
    pikemen = models.IntegerField(default=0)
    swordmen = models.IntegerField(default=0)
    riders = models.IntegerField(default=0)

    # Roman troops
    legionaries = models.IntegerField(default=0)
    praetorian = models.IntegerField(default=0)

我正试图以王国派系为基础,对军队进行系列化。在谈到own_troops时,它工作得很好,因为它们总是使用相同的序列化程序序列化,如下所示。

代码语言:javascript
复制
class CitySerializer(serializers.ModelSerializer):

    own_troops = serializers.SerializerMethodField()
    incoming_troops = serializers.SerializerMethodField()

    def get_own_troops(self, city_obj):
        if(KingdomModel.objects.get(owner=city_obj.owner).faction == "Gaul"):
            return GaulTroopsSerializer(instance=city_obj.own_troops, context=self.context, many=True, required=False, read_only=False).data
        elif(KingdomModel.objects.get(owner=city_obj.owner).faction == "Roman"):
            return RomanTroopsSerializer(instance=city_obj.own_troops, context=self.context, many=True, required=False, read_only=False).data
代码语言:javascript
复制
class RomanTroopsSerializer(serializers.ModelSerializer):
    class Meta:
        model = ArmyModel
        fields = ['id', 'home_city', 'current_city', 'target_city', 'status', 'action_done_time', 'settlers', 'legionaries', 'praetorian']

class GaulTroopsSerializer(serializers.ModelSerializer):
    class Meta:
        model = ArmyModel
        fields = ['id', 'home_city', 'current_city', 'target_city', 'status', 'action_done_time', 'settlers', 'pikemen', 'swordmen', 'riders']

但是,如果我试图将相同的逻辑应用于序列化incoming_troops,它将始终使用第一个序列化程序序列化列表中的所有对象。这是我在基于关系中的数据用不同的序列化器序列化每个外键的毫无希望的尝试。

代码语言:javascript
复制
    def get_incoming_troops(self, city_obj):
        for data in GaulTroopsSerializer(instance=city_obj.incoming_troops, context=self.context, many=True, required=False, read_only=False).data:
            print(data)
            home_city_obj = CityModel.objects.get(id=data['home_city'])
            if(KingdomModel.objects.get(owner=home_city_obj.owner).faction == "Gaul"):
                return GaulTroopsSerializer(instance=city_obj.incoming_troops, context=self.context, many=True, required=False, read_only=False).data
            else:
                return RomanTroopsSerializer(instance=city_obj.incoming_troops, context=self.context, many=True, required=False, read_only=False).data

    class Meta:
        model = CityModel
        fields = ['id', 'owner', 'city_name', 'x_coordinate', 'y_coordinate', 'last_updated', 'max_warehouse_capacity', 'max_grain_silo_capacity', 'wood_ammount', 'wheat_ammount', 'stone_ammount', 'iron_ammount', 'resource_fields', 'buildings','incoming_troops', 'own_troops',  'all_troops']
        read_only_fields = ['id', 'max_warehouse_capacity', 'max_grain_silo_capacity']

我知道我可以为所有不同派别的军队建立多个模型,但现在我只是想知道在django / drf中这是否可能?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-18 15:36:06

回答我自己的问题,因为我让它发挥作用,我做了以下几点:

首先,我刮了多个部队串行化器。而且只有一台军装连队,我在那里按派系交换战地。

这是我的ArmySerializer

代码语言:javascript
复制
class ArmySerializer(serializers.ModelSerializer):
class Meta:
    model = ArmyModel
    fields = ['id', 'home_city', 'current_city', 'target_city', 'status', 'action_done_time']  
    

def to_representation(self, instance):
    try:
        del self.fields # Clear the cache
    except AttributeError:
        pass

    if("faction" in self.context and len(self.context['faction']) > 0):
        print(self.context['faction'])
        self.fields['settlers'] = serializers.IntegerField()
        if(self.context['faction'][0] == "Gaul"):
            self.fields['pikemen'] = serializers.IntegerField()
            self.fields['swordmen'] = serializers.IntegerField()
            self.fields['riders'] = serializers.IntegerField()
        elif(self.context['faction'][0] == "Roman"):
            self.fields['legionaries'] = serializers.IntegerField()
            self.fields['praetorian'] = serializers.IntegerField()
        if(len(self.context['faction']) > 1):
            self.context['faction'].pop(0)
    
    
    return super().to_representation(instance)

在CitySerializer中,我正在填充上下文“派系”列表,如下所示:

代码语言:javascript
复制
class CitySerializer(serializers.ModelSerializer):

own_troops = serializers.SerializerMethodField()
incoming_troops = serializers.SerializerMethodField()


def get_own_troops(self, instance):
    if(KingdomModel.objects.get(owner=instance.owner).faction == "Gaul"):
        self.context["faction"] = ["Gaul"]
        return ArmySerializer(instance=instance.own_troops, context=self.context, many=True, required=False, read_only=False).data
    elif(KingdomModel.objects.get(owner=instance.owner).faction == "Roman"):
        self.context["faction"] = ["Roman"]
        return ArmySerializer(instance=instance.own_troops, context=self.context, many=True, required=False, read_only=False).data

def get_incoming_troops(self, city_obj):
    self.context['faction'] = []
    for data in ArmySerializer(instance=city_obj.incoming_troops, context=self.context, many=True, required=False, read_only=False).data:
        home_city = CityModel.objects.get(id=data['home_city'])
        sender_faction = KingdomModel.objects.get(owner=home_city.owner).faction
        if(sender_faction == "Gaul"):
            self.context['faction'] += ["Gaul"]
        else:
            self.context['faction'] += ["Roman"]
    return ArmySerializer(instance=city_obj.incoming_troops, context=self.context, many=True, required=False, read_only=False).data

也应该说,这给创建有岗位要求的军队带来了一个新的问题。在to_representation方法中动态添加的字段在默认情况下不进行验证,因此它们不存在于validated_data中。也许有一种方法可以覆盖验证,但我现在只是从原始请求数据中提取了它们,它似乎运行得很好。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65681587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档