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

时间:2019-07-18 12:53:18

标签: python django django-rest-framework django-authentication

我用DRF在Django中为User模型编写了一个序列化器:

模型:

from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import BaseUserManager
from django.db import models
from django.utils.translation import ugettext


class BaseModel(models.Model):
    # all models should be inheritted from this model
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True


class User(AbstractBaseUser, BaseModel):
    username = models.CharField(
        ugettext('Username'), max_length=255,
        db_index=True, unique=True
    )
    email = models.EmailField(
        ugettext('Email'), max_length=255, db_index=True,
        blank=True, null=True, unique=True
    )

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ('email', 'password',)

    class Meta:
        app_label = 'users'

序列化器:

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

有效。但是我可能在每次创建/更新时都进行两次调用而不是一次调用,并且代码看起来有些奇怪(不是DRY)。 有惯用的方法吗?

$python -V
Python 3.7.3

Django==2.2.3
djangorestframework==3.10.1

2 个答案:

答案 0 :(得分:1)

我希望这可以解决问题,

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

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

答案 1 :(得分:0)

您可以通过覆盖update so set SaleOrderQty = a.calc from SO so join (select sod.soid,sum((SOD.Quantity* SOD.PerPack)) as calc from sod group by sod.SOID) a on a.SOID=so.ID where so.SaleOrderQty is null --optional 并在其中使用BaseUserManager方法来创建自己的用户管理器。 django的documentation中有一个完整的示例。因此,您的set_password()将是:

models.py

然后,您可以在序列化程序的# models.py from django.db import models from django.contrib.auth.models import ( BaseUserManager, AbstractBaseUser ) class MyUserManager(BaseUserManager): def create_user(self, email, username, password=None): if not email: raise ValueError('Users must have an email address') user = self.model( email=self.normalize_email(email), username=username, ) user.set_password(password) user.save(using=self._db) return user class BaseModel(models.Model): # all models should be inheritted from this model created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) class Meta: abstract = True class User(AbstractBaseUser, BaseModel): username = models.CharField( ugettext('Username'), max_length=255, db_index=True, unique=True ) email = models.EmailField( ugettext('Email'), max_length=255, db_index=True, blank=True, null=True, unique=True ) # don't forget to set your custom manager objects = MyUserManager() USERNAME_FIELD = 'username' REQUIRED_FIELDS = ('email', 'password',) class Meta: app_label = 'users' 方法中直接调用create_user()。您还可以在自定义管理器中添加自定义更新方法。

create()