Django DRF: Принимать дополнительный ввод от пользователя с помощью сериализатора, но не присутствующий в модели
У меня есть один ModelSerializer класс, который используется для пользовательского ввода и валидации. Я использую его с ModelViewset, который автоматически создает новую запись в базе данных с помощью сериализатора. Теперь я хочу сделать следующее: я хочу иметь дополнительное поле в сериализаторе, скажем roles, которое будет задаваться пользователем. Это массив ролей для пользователя, но это поле не присутствует в модели & я хочу вручную добавить эту запись роли в таблицу auth_user_groups. Поэтому я написал свой сериализатор следующим образом,
class UserCreateSerializer(serializers.ModelSerializer):
"""
Serializer to create new user
"""
class Meta:
model = User
fields = ["name", "email", "is_active", "roles"]
read_only_fields = ['roles']
roles = serializers.MultipleChoiceField(choices=[(e.name,e.value) for e in AuthGroup])
def validate_roles(self, value):
if not value:
raise ValidationError(detail=constants.NAMED_FIELD_REQUIRED.format(field="roles"))
Моя модель выглядит следующим образом,
class User(AbstractBaseUser, PermissionsMixin):
class Meta:
db_table = "auth_user"
app_label = "users"
USERNAME_FIELD = "email"
REQUIRED_FIELDS = []
name = models.CharField(max_length=255, null=True)
email = models.EmailField("email address", unique=True, null=True)
is_active = models.BooleanField(default=True)
is_superuser = None
is_admin = None
is_verified = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = UserManager()
def __str__(self):
return self.name or self.email
def is_admin(self):
return self.groups.filter(name=AuthGroup.ADMIN.name).exists()
Это тело запроса, которое приходит от пользователя.
{
"name": "test4",
"email": "test4@example.com",
"is_active": true,
"roles": [
"ADMIN", "OPERATOR"
]
}
Я получаю эту ошибку всякий раз, когда пытаюсь вызвать API,
raise TypeError("%s() получил неожиданный аргумент ключевого слова '%s'" % (cls.name, kwarg)) TypeError: User() получил неожиданное ключевое слово аргумент 'roles'
У кого-нибудь есть идеи, как я могу решить эту проблему или достичь того, что я сказал выше? Любая помощь будет принята с благодарностью...
Это происходит потому, что проверенные данные передаются в метод create(...) из QuerySet внутри метода create(...) сериализатора. Поэтому необходимо раскрыть поле roles перед операцией создания.
class UserCreateSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ["name", "email", "is_active", "roles"]
roles = serializers.MultipleChoiceField(
choices=[(e.name, e.value) for e in AuthGroup],
required=True
)
def validate_roles(self, value):
# do some validations
return value
def create(self, validated_data):
roles = validated_data.pop("roles", None)
return super().create(validated_data)
Примечания
- Вы можете использовать
required=Trueдля установки поля как обязательного, чтобы не делать никаких дополнительных валидаций для него .
read_only_fieldsбудет работать для тех полей, которые не определены явно в сериализаторе.