Python Django和DRF:用户模型的序列化程序

Python Django和DRF:用户模型的序列化程序,python,django,django-rest-framework,django-authentication,Python,Django,Django Rest Framework,Django Authentication,我在Django中使用DRF为用户模型编写了一个序列化程序: 模型: 从django.contrib.auth.models导入AbstractBaseUser 从django.contrib.auth.models导入BaseUserManager 从django.db导入模型 从django.utils.translation导入ugettext 类BaseModel(models.Model): #所有模型都应从该模型继承 created=models.DateTimeField(auto

我在Django中使用DRF为用户模型编写了一个序列化程序:

模型:

从django.contrib.auth.models导入AbstractBaseUser
从django.contrib.auth.models导入BaseUserManager
从django.db导入模型
从django.utils.translation导入ugettext
类BaseModel(models.Model):
#所有模型都应从该模型继承
created=models.DateTimeField(auto\u now\u add=True)
updated=models.DateTimeField(auto\u now=True)
类元:
抽象=真
类用户(AbstractBaseUser、BaseModel):
用户名=models.CharField(
ugettext('Username'),最大长度=255,
db_index=True,unique=True
)
email=models.EmailField(
ugettext('Email'),最大长度=255,db\u索引=True,
blank=True,null=True,unique=True
)
用户名\字段='USERNAME'
必填字段=('email','password',)
类元:
应用程序标签='用户'
序列化程序:

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = ['email', 'username', 'password']
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        user = super().create(validated_data)
        user.set_password(validated_data['password'])
        user.save()
        return user

    def update(self, user, validated_data):
        user = super().update(user, validated_data)
        user.set_password(validated_data['password'])
        user.save()
        return user
它起作用了。但是我可能会在每次创建/更新时调用两个而不是一个,代码看起来有点奇怪(不枯燥)。 有没有一种惯用的方法

$python -V
Python 3.7.3

Django==2.2.3
djangorestframework==3.10.1

您可以通过覆盖
BaseUserManager
并在其中使用
set\u password()
方法来创建自己的用户管理器。django的书中有一个完整的例子。因此,您的
models.py
将是:

#models.py
从django.db导入模型
从django.contrib.auth.models导入(
BaseUserManager,AbstractBaseUser
)
类MyUserManager(BaseUserManager):
def create_用户(自我、电子邮件、用户名、密码=无):
如果不是电子邮件:
raise VALUERROR('用户必须有电子邮件地址')
user=self.model(
电子邮件=自我规范化电子邮件(电子邮件),
用户名=用户名,
)
user.set_密码(password)
user.save(使用=self.\u db)
返回用户
类BaseModel(models.Model):
#所有模型都应从该模型继承
created=models.DateTimeField(auto\u now\u add=True)
updated=models.DateTimeField(auto\u now=True)
类元:
抽象=真
类用户(AbstractBaseUser、BaseModel):
用户名=models.CharField(
ugettext('Username'),最大长度=255,
db_index=True,unique=True
)
email=models.EmailField(
ugettext('Email'),最大长度=255,db\u索引=True,
blank=True,null=True,unique=True
)
#别忘了设置自定义管理器
objects=MyUserManager()
用户名\字段='USERNAME'
必填字段=('email','password',)
类元:
应用程序标签='用户'
然后,可以在序列化程序的
create()
方法中直接调用
create\u user()
。还可以在自定义管理器中添加自定义更新方法

#serializers.py
类UserSerializer(serializers.ModelSerializer):
类元:
model=models.User
字段=[“电子邮件”、“用户名”、“密码”]
extra_kwargs={'password':{'write_only':True}
def创建(自我验证的_数据):
用户=models.user.objects.create\u用户(
用户名=已验证的_数据['username'],
电子邮件=已验证的_数据['email'],
密码=已验证的_数据['password']
)
返回用户

我希望这能解决这个问题

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.User
        fields = ['email', 'username', 'password']
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        return models.User.objects.create_user(**validated_data)

    def update(self, user, validated_data):
        password = validated_data.pop('password', None)
        if password is not None:
            user.set_password(password)
        for field, value in validated_data.items():
            setattr(user, field, value)
        user.save()
        return user
class UserSerializer(serializers.ModelSerializer):
类元:
model=models.User
字段=[“电子邮件”、“用户名”、“密码”]
extra_kwargs={'password':{'write_only':True}
def创建(自我验证的_数据):
返回models.User.objects.create\u User(**已验证的\u数据)
def更新(自我、用户、已验证的_数据):
password=validated_data.pop('password',None)
如果密码不是“无”:
user.set_密码(password)
对于字段,验证的_data.items()中的值:
setattr(用户、字段、值)
user.save()
返回用户

create_user()
方法使用
set_password()
方法设置哈希密码。

我需要调用模型的
set_password
save
。或者我需要调用
create\u user
,但是我不能在序列化程序中调用
create
上的super-在这里您可以通过一些测试找到代码。试试你的建议。并尝试运行测试“我可能会执行两个调用,而不是每次创建/更新一个”两个调用?怎样我不明白
user=super()。创建(已验证的数据)
是的,它应该可以工作。唯一的问题是:在这种情况下,我们不调用序列化程序的super。它包含一些代码。你的意见是什么,这是个问题吗?它有一些与验证相关的代码。除非您试图保存一些关系数据(
FK
M2M
字段),否则不会有问题