Сочетание функций сериализатора и модели - PullRequest
7 голосов
/ 11 июля 2019

У меня есть два сериализатора ... MyRegisterSerializer наследует и расширяет популярное приложение / пакет django-rest-auth, которое подключается к довольно стандартной пользовательской таблице. У меня также есть Модель и сериализатор для пользовательского приложения, TeamSerializer (отношения один-ко-многим с пользователями). Когда пользователь регистрируется, я бы хотел, чтобы он мог присоединиться к команде одновременно, поэтому мне нужно каким-то образом создать команду, вернуть идентификатор команды, а затем передать этот идентификатор в RegisterSerializer, чтобы идентификатор Команда может храниться в пользовательской таблице. Я знаю, что мог бы сделать два вызова, сначала создать команду и вернуть значение, а затем передать его сериализатору регистра, но есть ли способ сделать все это в одном сериализаторе? Я n00b в Python, и не могу найти отличный пример этого, учитывая, что я должен вернуть функцию get_cleaned_data() как есть. Спасибо!

class TeamSerializer(serializers.ModelSerializer):

  class Meta:
    model = Team
    fields = ('id', 'name', 'logo', 'user')

class MyRegisterSerializer(RegisterSerializer):
  first_name = serializers.CharField()
  last_name = serializers.CharField()

  def get_cleaned_data(self):
    super(MyRegisterSerializer, self).get_cleaned_data()
    return {
        'team_id': <How do I get this value>
        'username': self.validated_data.get('username', ''),
        'position': self.validated_data.get('password1', ''),
        'email': self.validated_data.get('email', ''),
        'first_name': self.validated_data.get('first_name', ''),
        'last_name': self.validated_data.get('last_name', '')
    }

1 Ответ

4 голосов
/ 14 июля 2019

Зависит от того, как вы хотите создать команду:

1. Команда создается по другой информации:

Вы должны использовать это настраиваемое поле:

from rest_framework.relations import PrimaryKeyRelatedField

class TeamPrimaryKeyRelatedField(PrimaryKeyRelatedField):
    def to_internal_value(self, data):
        if self.pk_field is not None:
            data = self.pk_field.to_internal_value(data)
        try:
            obj, created = self.get_queryset().get_or_create(
                pk=data,
                defaults=get_team_data(),
            )
            return obj
        except (TypeError, ValueError):
            self.fail('incorrect_type', data_type=type(data).__name__)

И используйте его в своем сериализаторе:

class MyRegisterSerializer(RegisterSerializer):
    team = TeamPrimaryKeyRelatedField()
    # ...

2. Используйте дополнительный пользовательский ввод для создания команды:

Это выглядит как идеальный вариант использования для записываемых вложенных сериализаторов :

class TeamSerializer(serializers.ModelSerializer):
    class Meta:
        model = Team
        fields = ('id', 'name', 'logo', 'user')

class MyRegisterSerializer(RegisterSerializer):
  first_name = serializers.CharField()
  last_name = serializers.CharField()
  team = TeamSerializer()

    def create(self, validated_data):
        team_data = validated_data.pop('team')
        # You could do this if the user is not necessary in the team object:
        team = Team.objects.create(**team_data)
        user = super().create(team=team, **validated_data)

        # Otherwise:
        user = super().create(**validated_data)
        # Should this be a many-to-many relationship?
        team = Team.objects.create(user=user, **team_data)
        # I don't know if this works/you need it:
        self.team = team
        # Or it should be like this?
        self.validated_data['team'] = team
        return user

Я не уверен, что именно вам нужно. Дайте мне знать, если вам понадобится дополнительная помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...