如何在POST请求期间获取额外的JSON数据

时间:2019-08-28 19:34:15

标签: python django django-rest-framework

我的目标是接收一个JSON,其中包含创建用户所需的所有信息,以及将用于创建另一个对象的其他一些东西,这些都将使用最近创建的用户以及通过JSON。对于上下文,我的JSON当前如下所示:

{
   "first_name": "John",
   "last_name": "Doe",
   "username": "newuser",
   "email": "johndoe@hotmail.com",
   "password": "somepassword",
   "profile_image": null,
    "type": 2
}

type是创建用户不必要的信息。目前,我的自定义创建函数如下所示:

class UserSerializer(ModelSerializer):
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'username', 'email', 'id', 'password', 'profile_image']
        read_only_fields = ['id', 'created_at', 'updated_at', 'is_staff']

    def create(self, validated_data):
        new_user = User.objects.create_user(**validated_data)
        types = self.request.data.get("type")
        create_user_type = UserType.objects.create(user=new_user, type=types)
        return create_user_type

查看Django Rest Framework文档,stackoverflow问题和调试后,它发生了很多变化。如果我按现在的方式运行代码,这就是我得到的:

AttributeError at /user/
'UserSerializer' object has no attribute 'request'

所以我认为发生这种情况是因为您无法通过执行self.request来获得请求。我尝试将其创建到视图集中,因为我意识到那里的工作略有不同,但是随后发生了:

TypeError at /user/
create_user() argument after ** must be a mapping, not Request

我可以编辑问题以添加我忘记的任何信息。我还应该注意,无论错误如何,都会创建用户,但是我的目标是创建用户和另一个对象。我怎么能从自我中得到打字?

3 个答案:

答案 0 :(得分:0)

简单地说,您无法从self获得它,但是您可以从其他地方获得它。

如果您注意到第二个错误,则显示为

TypeError at /user/
create_user() argument after ** must be a mapping, not Request

这意味着在new_user = User.objects.create_user(**validated_data)定义中,validated_data是您要传递的Request对象。

您可以尝试validated_data.get("type")来获取类型!

免责声明:确保您的API安全。我对此还很陌生,不确定传递整个请求对象是否安全

编辑: 了解传递给函数的对象的数据类型将为您澄清很多事情。将代码块移至视图集之后,您是否更改了界面的方式?

编辑(2): 在这里回复您的评论:

types = self.request.data.get("type")

Request对象很可能具有反序列化的数据,这在Python中通常表示dict() type对象。这就是为什么可以在该对象上使用.get()的原因(除非您将cls指定为一个钩子,以不同方式解释数据)。

这意味着,序列化JSON支持的数据类型(字符串,数字,列表/数组,JSON对象)在Python中将为str / bytes / unicode,int / float,list,dict。

因此,type(types)实际上看起来像是int。 (您说的是注释中的"2",对吗?在这种情况下,您的type(types)应该给出str)。

如果要在下一个命令中使用此值,则可能必须创建Types类的对象,并将该值传递到其构造函数中(我不知道它的外观,只是一个猜测)

create_user_type = UserType.objects.create(user=new_user, type=types)

这应该可以解决您的问题,或者至少让您更好地理解它...

答案 1 :(得分:0)

在我看来,请求尚未定义。我希望可以在您的课程下看到导入或定义的方法。

在您的项目中四处寻找调用request()的其他类,然后看看您发现了什么。

答案 2 :(得分:0)

可以更优雅地解决这个问题。

class UserSerializer(ModelSerializer):
  type = serializers.IntegerField(write_only=True, required=False) #optionl 'type' integer field

  class Meta:
    model = User
    fields = ['first_name', 'last_name', 'username', 'email', 'id', 'password', 'profile_image', 'type']
    read_only_fields = ['id', 'created_at', 'updated_at', 'is_staff']

  def create(self, validated_data):
     type = validated_data.pop('type')
     user = super(UserSerializer, self).create(validated_data)
     create_user_type = UserType.objects.create(user=user, type=type)
     return user

UserSerializer不会返回UserType对象。它将引发错误。 如果要与UserType对象一起返回User对象,则必须为Usertype创建一个单独的序列化器,并将其用作嵌套在UserSerializer中的序列化器。