Сериализация Django - частичное обновление вложенных объектов

Поискал несколько часов на эту тему и удивлен, что не нашел ответа, но вот он.

Допустим, у меня есть следующие модели:

class Mission(models.Model):
    mission_name = models.CharField(max_length=150)
    ...

class Player(models.Model):
    player_name = models.CharField(max_length=150, unique = True)
    state = models.CharField(max_length=150)
    currentMission = models.ForeignKey(Mission,on_delete=models.SET_NULL, blank=True, null=True)) 

Цели:

  1. When creating a mission, I would like to provide the players' names that are going to participate on this mission (Names are unique). That means, when mission is created, I have to update the currentMission field of each given player. (Players already exist when mission is created)
  2. When I try to GET a mission, I would like to see the names of the players that participate

Моя попытка

Class MissionSerializer(serializers.ModelSerializer):
    
    #This is to get a list of the players that participate in this mission
    players = PlayerSerializer(many=True,  read_only=True) 
    class Meta:
        model= Mission
        fields = ['mission_name','players']


    def create(self,validated_data):
        mission = Mission.objects.create(**validated_data)
                
                
        # Notice that I get the "players" data from "self.initial_data" and not from validated_data
        # This is because validated_data does not have the "players" field,
        # (I guess because I didn't provide all the required fields on my request for the player. I just provided the players' names )
        players_data = self.initial_data['players']

        #Update each player's current mission
        for player_data in players_data:
            qs = Player.objects.filter(player_name=player_data['player_name'])
            obj = get_object_or_404(qs)
            serializer = PlayerSerializer(obj, data={'currentMission': mission.id}, partial=True)
            if (serializer.is_valid()):
                serializer.save()


class PlayerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Player
        fields = ('__all__')

    def update(self, instance, validated_data):
        instance.currentMission = validated_data['currentMission']
        instance.save()
        return instance

Вышеизложенное работает для цели №1. Однако это не работает для цели #2. То есть, когда я GET выполняю миссию, список игроков не присутствует в результате.

Мой вопрос в том, как я могу также получить этот список при выполнении GET запросов?

Я думаю, что в поле players отсутствует источник. Добавление источника к полю должно решить вашу проблему.

players = PlayerSerializer(many=True,  read_only=True, source='player_set')

Кроме того, я бы рекомендовал предварительную выборку игроков для оптимизации запроса к базе данных.

По вашему мнению;

mission_queryset = Mission.objects.filter(...).prefetch_related('player_set')
Вернуться на верх