1

Я пытаюсь понять, как справиться с вложенными моделями в django-rest-framework (DRF). Я прочитал this part of the documentation, который посвящен написанию сериализатора, который может сохранять вложенные объекты, но это не совсем то, что я хочу. В сообщении у меня есть идентификаторы связанных объектов (многие-ко-многим).Как создать объект со ссылкой на вложенный объект из идентификатора в POST

Пример:
Допустим, у меня есть матч (думаю, футбол, теннис), а матч между двумя командами, а команды состоят из игроков. Я хочу отправить POST с информацией о совпадении и идентификаторами игроков. Если игроки играли до того, как уже есть команда, в противном случае мы должны сделать команду.

Если игрок 1 играл игру 4 против игрока, 2, POST будет выглядеть как

team_1[player_1_id]:1 // 1st player of team 1 is user 1 
team_2[player_1_id]:2 // 1st player of team 2 is user 2 
game:4 

Тот факт, что все виды вещей должно быть сделано, я, возможно, думал, что view было хорошее место: мне нужно перетасовывать некоторые данные до того, как они будут готовы к сериализатору; но как мне начать?

я могу переопределить perform_create сделать магию так:

class MatchViewSet(viewsets.ModelViewSet): 
    queryset = Match.objects.all() 
    serializer_class = MatchSerializer 

    def perform_create(self, serializer): 
    // get the user ids form the post 
    // find if there is are teams, otherwise create the teams 
    // get team ids from above 
    // add team ids to data so serializer kan save 
    serializer.save() 

Так что мне нужно, чтобы выяснить

  • как получить идентификатор с поста
  • как получить право team-ids (и, возможно, создать их в первую очередь)
  • как передать их на сериализаторе.

В частности, что из этих функций можно сделать, используя функции на месте DRF и/или ModelViewSet. Я также пытаюсь изучить структуру здесь :)

Модели выглядят следующим образом. Я не хочу сохранять полный вложенный объект, поэтому я не думаю, что мне нужно добавить конкретный create здесь?

class Match(models.Model): 
    game = models.ForeignKey(Game) 
    teams = ManyToManyField(Team, through='MatchTeams') 

другие модели, которые могут быть актуальны;

class MatchTeams(models.Model): 
    match = models.ForeignKey(Match) 
    team = models.ForeignKey(Team) 

class Team(models.Model): 
    name = models.TextField(max_length=128) 
    users = ManyToManyField(User, through='TeamUsers') 
+0

Я предполагаю, что 'team2' в почтовых данных должны содержать идентификатор Player2? – Sayse

+0

@Sayse Идентификаторы - это команды, поэтому само по себе: это не ясно из этого минимизированного примера, но он определяется как первый игрок из второй команды (так что если в команде было 2 игрока, то вы получили бы игрока 2 также). Вот почему на этом посту есть два игрока-id-1. Один для каждой команды :) – Nanne

+0

Хорошо, да, это имеет смысл. Я не уверен, что у меня достаточно времени, чтобы предоставить полный ответ, но вы можете найти способ 'def create (self, request)' намного легче работать, поскольку, по сути, вы будете делать то же самое работайте, как если бы это было представление django - позволяя использовать 'get_or_create' и т. д. – Sayse

ответ

2

Я думаю, что вы должны сделать специальную сериалайзер: http://www.django-rest-framework.org/api-guide/serializers/#saving-instances

Что-то вроде этого:

class MatchSerializer(serializers.Serializer): 
    player_1 = serializers.IntegerField() 
    player_2 = serializers.IntegerField() 
    id = serializers.IntegerField() 

    def create(self, validated_data): 
     try: 
      team = Team.objects.filter(Q(users__id=player_1 & users__id=player_2)) 
     except Team.DoesNotExcist: 
      team = Team.objects.create() 
      team.users.add(player_1) 
      team.users.add(player_2) 
      team.save() 
     match = super(serializers.Serializer, self) 
     match.teams.add(team) 
     # Something like this, but you have to post both team members at once. Can be made so you don't have to oc. You also might want to check the count of teams before adding them :-) 
     return match 

    def update(self, instance, validated_data): 
     # same as create but on a given match? 
     return instance 

ли эту работу для ваших нужд? Лучший способ - разрешить подобные вещи в Serializers, для чего они предназначены, конвертируя поля запроса в соответствующие объекты/поля.

Тем не менее, если вы хотите сделать что-то простое, всегда self.request вы можете получить доступ к вашему ModelViewSet

+0

Итак, я создаю конкретную конечную точку (ModelViewSet), которая использует этот сериализатор и обрабатывает всю логику здесь. звучит хорошо. Меня повесили на сериализаторах для моих моделей, но это не обязательно должно быть так. хорошая точка зрения. – Nanne

+0

мелкий вопрос: модель ModelViewSet кажется на основе конкретной модели, которая на самом деле не здесь в данном случае, не так ли? У меня только сериализатор и представление. Какой вид я должен определить, что позволит мне публиковать сообщения? Не так много нужно, я думаю, на этом этапе? – Nanne