Python Django序列化程序从post访问json数据(字符串索引必须是整数)

Python Django序列化程序从post访问json数据(字符串索引必须是整数),python,django,validation,django-rest-framework,serialization,Python,Django,Validation,Django Rest Framework,Serialization,我正在尝试为register post请求的验证创建序列化程序 通过POST请求发送到API的json: { "username": "dat@icts.vn", "password": "123456", "confirm_password": "123456" } 用于验证的我的序列化程序: class RegisterSerializer(serializers.Serializer): username = serializers.EmailField(

我正在尝试为register post请求的验证创建序列化程序 通过POST请求发送到API的json:

{
    "username": "dat@icts.vn",
    "password": "123456",
    "confirm_password": "123456"
}
用于验证的我的序列化程序:

class RegisterSerializer(serializers.Serializer):
    username = serializers.EmailField(required=True)
    password = serializers.CharField(required=True)
    confirm_password = serializers.CharField(required=True)

    def validate_username(self, username):
        existing_email = User.objects.filter(email=username).first()
        if existing_email:
            raise serializers.ValidationError("Email already registered")

        return username
    def validate_confirm_password(self, data):
        if data['password']:
            if data['confirm_password'] != data['password']:
                raise serializers.ValidationError("Confirm password not match password")

            return data['confirm_password']
我的视图寄存器功能:

@csrf_exempt
@require_http_methods(["POST"])
def register(request):
    received_json_data=json.loads(request.body)
    valid_ser = RegisterSerializer(data=received_json_data)
    if valid_ser.is_valid():
        post_username = received_json_data["username"]
        post_password = received_json_data["password"] 
        user = User.objects.create_user(username=post_username,password=post_password)
        user.save()
        refresh = RefreshToken.for_user(user)

        content = {
            'refresh': str(refresh),
            'access': str(refresh.access_token),
        }

        return JsonResponse(content)
    else:
        return JsonResponse({'code':'400','errors':valid_ser.errors}, status=400)
发送POST请求时,出现以下错误:

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
web_1       |     response = get_response(request)
web_1       |   File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
web_1       |     response = self.process_exception_by_middleware(e, request)
web_1       |   File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
web_1       |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
web_1       |   File "/usr/local/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
web_1       |     return view_func(*args, **kwargs)
web_1       |   File "/usr/local/lib/python3.6/site-packages/django/views/decorators/http.py", line 40, in inner
web_1       |     return func(request, *args, **kwargs)
web_1       |   File "/app/api/views.py", line 84, in register
web_1       |     if valid_ser.is_valid():
web_1       |   File "/usr/local/lib/python3.6/site-packages/rest_framework/serializers.py", line 235, in is_valid
web_1       |     self._validated_data = self.run_validation(self.initial_data)
web_1       |   File "/usr/local/lib/python3.6/site-packages/rest_framework/serializers.py", line 430, in run_validation
web_1       |     value = self.to_internal_value(data)
web_1       |   File "/usr/local/lib/python3.6/site-packages/rest_framework/serializers.py", line 489, in to_internal_value
web_1       |     validated_value = validate_method(validated_value)
web_1       |   File "/app/api/views.py", line 49, in validate_confirm_password
web_1       |     if data['password']:
web_1       | TypeError: string indices must be integers
web_1       | [05/Sep/2019 04:59:33] "POST /api/register HTTP/1.1" 500 99431

似乎我无法用序列化器中的密钥访问json数据变量,我有点被困在这个问题上。任何帮助都将非常感谢。

它类似于
validate\u username(self,username)
方法,
validate\u confirm\u password(self,data)
中的
data
参数实际上是密码值,它是一个字符串


Ref

您应该将函数
validate\u confirm\u password
重命名为
validate

如前一个响应中所述,
validate{field_name}
用作并将接收/返回实际字段的值,而不是当前数据

相反,您要做的是使用
验证
(例如)

在您的情况下,这将给出:

class RegisterSerializer(serializers.Serializer):
    username = serializers.EmailField(required=True)
    password = serializers.CharField(required=True)
    confirm_password = serializers.CharField(required=True)

    def validate_username(self, username):
        existing_email = User.objects.filter(email=username).first()
        if existing_email:
            raise serializers.ValidationError("Email already registered")

        return username

    def validate(self, data):
        if data['password']:
            if data['confirm_password'] != data['password']:
                raise serializers.ValidationError("Confirm password not match password")

        return data

validate\u fieldname(self,fieldvalue)
中,您将获得要验证的字段的实际值

由于您已使用username值直接过滤
validate\u username
方法中的现有记录

但是在
validate\u confirm\u password
方法中,您试图验证密码,这是不正确的方法

要根据完整的请求进行验证,您可以使用
validate
方法

def validate(self, data):
    username = data["username"]
    password = data["password"]
    confirm_password = data["confirm_password"]
    # your validation  logic
正如上面所说:

我们对初始数据进行了两级验证:

:

您可以通过向序列化程序子类添加。
validate\uu
方法来指定自定义字段级验证。这些方法类似于Django表单上的。
clean
方法

示例:

from rest_framework import serializers

class BlogPostSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)
    content = serializers.CharField()

    def validate_title(self, value):
        """
        Check that the blog post is about Django.
        """
        if 'django' not in value.lower():
            raise serializers.ValidationError("Blog post is not about Django")
        return value
from rest_framework import serializers

class EventSerializer(serializers.Serializer):
    description = serializers.CharField(max_length=100)
    start = serializers.DateTimeField()
    finish = serializers.DateTimeField()

    def validate(self, data):
        """
        Check that start is before finish.
        """
        if data['start'] > data['finish']:
            raise serializers.ValidationError("finish must occur after start")
        return data
注意:如果在序列化程序上使用参数
required=False声明了
,则如果未包含该字段,则不会执行此验证步骤

:

要执行需要访问多个字段的任何其他验证,请将名为
.validate()
的方法添加到序列化程序子类中。此方法采用单个参数,即字段值字典。如果需要,它应该引发serializers.ValidationError,或者只返回已验证的值

示例:

from rest_framework import serializers

class BlogPostSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)
    content = serializers.CharField()

    def validate_title(self, value):
        """
        Check that the blog post is about Django.
        """
        if 'django' not in value.lower():
            raise serializers.ValidationError("Blog post is not about Django")
        return value
from rest_framework import serializers

class EventSerializer(serializers.Serializer):
    description = serializers.CharField(max_length=100)
    start = serializers.DateTimeField()
    finish = serializers.DateTimeField()

    def validate(self, data):
        """
        Check that start is before finish.
        """
        if data['start'] > data['finish']:
            raise serializers.ValidationError("finish must occur after start")
        return data
因此,您应该在
validate(data)
方法中验证
confirm\u password
,您可以这样访问数据:

def validate(data):

    confirm_password = data.get('confirm_password', None)
    password = data.get('password', None)

    # don't forget to return validated data
    return data


您在哪里呼叫
validate\u confirm\u password
?感谢您的解释,我直到现在才知道,我还必须更改ValidationError,否则它将显示错误字段属于非字段错误,这不是正确的响应。ValidationError({'confirm_password':['confirm password not match password']})