django User类型的对象不可JSON序列化

mv1qrgav  于 2023-03-04  发布在  Go
关注(0)|答案(2)|浏览(139)

我正在尝试为用户创建一个注册方法。用户模型如下所示:

class User(AbstractBaseUser):
  name = models.CharField(max_length=128, blank=False)
  created_at = models.DateTimeField(auto_now_add=True)
  is_admin = models.BooleanField(blank=True,default=False, verbose_name="Is admin")
  designation = models.CharField(max_length=90, blank=True)
  email = models.EmailField(max_length=160, blank=False, unique=True)
  password = models.TextField(blank=False)

  USERNAME_FIELD = "email"

  def __str__(self):
    return self.name + " " + self.email

序列化器如下所示:

class UserSerializer(serializers.ModelSerializer):
  class Meta:
    model = User
    fields = ["id", "name", "designation", "is_admin", "email", "password"]
    extra_kwargs = {
      'password': {'write_only': True}
    }
  
  #creates user after hashing
  #and salting password
  def create(self, validated_data):
    user = User.objects.create(
      name=validated_data.get('name'),
      email=validated_data.get('email'),
      password=make_password(password=validated_data.get('password'), salt=get_random_string(length=32))
    )
    return user

该视图

class AuthViewset(viewsets.ViewSet):
    def signUp(self, request, **kwargs):
        serializer = UserSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        is_new = True
        user = User.objects.filter(email=request.data['email']).first()

        if user is not None:
            #user exists
            is_new = False
        else:
            #create user
            user = serializer.create(serializer.validated_data)

        if is_new:
          return Response({
              "user": user,
              "message": "Created new user"
          }, status=status.HTTP_201_CREATED)
        else:
            return Response({
            "message": "User already exists"
        }, status=status.HTTP_409_CONFLICT)

我重写了create方法以允许对散列密码进行salting,我想让view方法获得创建的用户,所以我从create方法返回user对象,但是它抛出一个错误,显示

Object of type User is not JSON serialiable

我是django的新手,所以我很坚韧理解为什么会发生这种情况。我该怎么解决这个问题呢?

jum4pzuy

jum4pzuy1#

总的来说,你可以在你的代码中改进很多东西。但是,直接解决你的问题。ViewSet没有名为signUp的动作,将其更改为create,尽管主要问题与你正在返回的**数据 * 有关。
您将返回一个模型示例,因为:

user = serializer.create(serializer.validated_data)

相反,您需要的是返回序列化的数据,可以使用serializer.data访问这些数据。

def create(self, request, **kwargs):
    ...

    # You are returning a model instance, just send the serializer.data
    if is_new:
        return Response({
            "user": serializer.data,
            "message": "Created new user"
        }, status=status.HTTP_201_CREATED)
    else:
        ...

关于改进,请看这个例子。您的模型没有manager,这将有助于散列密码和使用management命令createsuperuser。现在的情况是,无法使用管理页面,这是框架的一个强大特性。
最后,你可以去掉password字段,你只是覆盖了AbstractBaseUser密码。并且,重命名AuthViewset,因为它不是一个认证,而是一个注册端点。

xxhby3vn

xxhby3vn2#

这是因为当你试图返回Response({"user": user...时,一个模型示例不能被直接序列化,因为python不知道如何将user转换成JSON,所以它不能被完成。要解决这个问题,我们可以手动序列化它,如下所示:

return Response({
    "user": { 'name': user.name, 'email': user.email },
    "message": "Created new user"
}, status=status.HTTP_201_CREATED)

或者更好的方法是使用Serializer。如果您允许,我想建议对视图实现进行一些更改:

class AuthViewset(viewsets.ViewSet):
    def signUp(self, request, **kwargs):
        serializer = UserSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        if User.objects.filter(email=serializer.validated_data['email']).exits():
            return Response({
                "message": "User already exists"
            }, status=status.HTTP_409_CONFLICT)

        serializer.save()
        
        return Response({
            "user": serializer.data,
            "message": "Created new user"
        }, status=status.HTTP_201_CREATED)

永远不要做“如果-否则”的噩梦。

相关问题