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(...)方法内的QuerySetcreate(...)方法。因此,您需要在创建操作之前弹出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,
write_only=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将适用于那些而不是在序列化程序中显式定义的字段

相关内容

最新更新