【问题标题】:DjangoRestFramework serializing custom user modelsDjangoRestFramework 序列化自定义用户模型
【发布时间】:2013-05-10 03:38:58
【问题描述】:

我已经定义了一个自定义用户模型类如下

class LabUserManager(BaseUserManager):
    """
    A new user manager for both standard and administrative users
    """

    def create_user(
            self, 
            email,
            first_name,
            last_name,
            university,
            job_title,
            bio,
            password=None
    ):
        """
        Creates a standard user with no administrative privledges
        """
        if not email:
            raise ValueError('Users must provide an email')

        if not first_name:
            raise ValueError('Users must provide a first name')

        if not last_name:
            raise ValueError('Users must provide a last name')

        if not university:
            raise ValueError('Users must provide an email address')

        # Note: a biography and job_title are not required
        user.set_password(password)
        user.save(using=self._db)
        return user


    def create_superuser(
            self, 
            email,
            first_name,
            last_name,
            university,
            job_title,
            bio,
            password=None
    ):
        """
        Creates an administrative user
        """    

        user = self.create_user(
            self, 
            email,
            first_name,
            last_name,
            university,
            job_title,
            bio,
            password=None
        )
        user.is_admin = True
        user.save(using=self._db)
        return user                

class LabUser(AbstractBaseUser):
    """
    Model for every user on the site
    The only required fields are:
        email,
        first_name,
        last_name,
        university,
    although, this will be discussed later
    """
    email = models.EmailField(
        verbose_name = 'email address',
        max_length   = 255,
        unique       = True,
        db_index     = True,
    )
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    university = models.CharField(max_length=150)
    job_title = models.CharField(max_length = 50)
    bio = models.TextField()
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)
    created = models.DateTimeField(auto_now_add=True)

    objects = LabUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = [
        'first_name',
        'last_name',
        'university',
    ]

    @property 
    def is_staff(self):
        return self.is_admin

使用序列化器

class NewUserSerializer(serializers.Serializer):
    """
    Defines a new user serializer
    """
    pk = serializers.Field()
    email = serializers.EmailField()
    first_name = serializers.CharField(max_length=50)
    last_name = serializers.CharField(max_length=50)
    university = serializers.CharField(max_length=150)
    job_title = serializers.CharField(
        max_length=50,
        required=False
    )
    bio = serializers.CharField(
        widget=widgets.Textarea,
        required=False
    )
    password = serializers.CharField(
        max_length=64,
        widget=widgets.PasswordInput
    )

    def restore_object(self, attrs, instance=None):
        if instance: # Update email university bio or job_title
            user = instance
            user.email = attrs['email']
            user.university = attrs['university']
            user.bio = attrs['bio']
            user.job_title = attrs['job_title']
            user.set_password(attrs.get('password'))
        else:
            user = LabUser(
                email=attrs['email'],
                first_name=attrs['first_name'],
                last_name=attrs['last_name'],
                university=attrs['university'],
                job_title=attrs['job_title'],
                bio=attrs['bio']
                # Check custom user model page for other parameters
            )
            user.set_password(attrs.get('password'))
            user.save()
        return user

与视图

class NewUser(generics.CreateAPIView):
    serializer_class = NewUserSerializer

但是当我使用新电子邮件地址发布新用户时,我收到以下错误

IntegrityError at /users/new/
PRIMARY KEY must be unique
Request Method: POST
Request URL:    http://127.0.0.1:8000/users/new/
Django Version: 1.5.1
Exception Type: IntegrityError
Exception Value:    
PRIMARY KEY must be unique

【问题讨论】:

    标签: django serialization unique django-rest-framework


    【解决方案1】:

    在某些时候,您似乎在创建新对象时提交并处理了主键值。这只是一个猜测,但我认为这发生在您的 NewUserSerializer 的某个地方,因为您明确添加了一个 pk 字段,该字段不是只读的并且不强制执行正整数值。我会尝试将IntegerFieldread_only=True 一起使用,看看是否能解决问题。

    但我还是强烈推荐使用ModelSerializer。您仍然可以为每个字段使用自定义小部件,但它还可以处理一些比您的实现更简洁的事情。而且您必须编写更少的代码。

    【讨论】:

    • 模型序列化程序的唯一问题是我无法定义哪些字段是可选的。当然,除非我错了。如果是这种情况,请给我一个带有详细解释的明确示例,以便我可以将其添加到文档中?我相信社区中的每个人都会感激不尽。
    • 只需在模型序列化程序上明确定义字段(而不是仅通过 Meta 类)并将 required=False 传递给字段构造器。 required 实际上是一个核心参数,可用于任何可写字段。
    猜你喜欢
    • 2016-08-08
    • 1970-01-01
    • 2015-12-14
    • 2013-05-02
    • 2017-02-08
    • 2014-10-05
    • 2017-04-08
    • 2018-02-04
    • 2019-04-28
    相关资源
    最近更新 更多