Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django Rest框架:如果嵌套序列化程序中的可选字段为空,则PUT/POST失败_Django_Django Rest Framework - Fatal编程技术网

Django Rest框架:如果嵌套序列化程序中的可选字段为空,则PUT/POST失败

Django Rest框架:如果嵌套序列化程序中的可选字段为空,则PUT/POST失败,django,django-rest-framework,Django,Django Rest Framework,我使用的是Django 1.7版和Django Rest框架3.1.3版 我有两个相互关联的模型,如下所示: class Person(models.Model): name = models.CharField(max_length=200) GENDER_CHOICES = ( ('M', 'Male'), ('F', 'Female'), ('T', 'Transgender'), ) gender

我使用的是Django 1.7版和Django Rest框架3.1.3版

我有两个相互关联的模型,如下所示:

class Person(models.Model):
    name = models.CharField(max_length=200)     
    GENDER_CHOICES = (
        ('M', 'Male'),
        ('F', 'Female'),
        ('T', 'Transgender'),
    )
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
    address = models.CharField(max_length=1000)
    work_phone = models.CharField(max_length=15, blank=True, null=True,
                        validators=[RegexValidator(regex='^[0-9]+$', 
                        message='Phone number must contain only digits', 
                        code='nomatch')])
    home_phone = models.CharField(max_length=15, blank=True, null=True,
                        validators=[RegexValidator(regex='^[0-9]+$', 
                        message='Phone number must contain only digits', 
                        code='nomatch')])
    mobile = models.CharField(max_length=15, blank=True, null=True,
                        validators=[RegexValidator(regex='^[0-9]+$', 
                        message='Phone number must contain only digits', 
                        code='nomatch')])
    email = models.EmailField(blank=True)
    date_of_birth = models.DateField()
    user = OneToOneField(User, null=True, blank=True)   
    DOCUMENT_CHOICES = (
        ('DL', 'Driving License'),
        ('RC', 'Ration card'),
        ('PP', 'Passport'),
        ('NO',  'None'),                 
    )
    additional_document = models.CharField(max_length=2, choices=DOCUMENT_CHOICES)
    document_number = models.CharField(max_length=10, blank=True, null=True)
    document_scan = models.FileField(max_length=1000, blank=True, null=True)
    photo = models.ImageField(blank=True,null=True)

class Admin(models.Model):
    person = OneToOneField(Person)
    # More fields will be added later
所以Person包含一个指向用户的OneToOne字段(Django的auth_用户模型),Admin包含一个指向Person的OneToOne字段。但是,我想为最终用户提供一个屏幕,一次更新所有这些细节(类似于在一个模板中组合多个模型)

我已经创建了与这些模型对应的显式序列化程序,它们具有如下嵌套关系

class UserSerializer(serializers.Serializer):
    id = serializers.IntegerField(label='ID', read_only=True)
    username = serializers.CharField(max_length=30)
    password = serializers.CharField(max_length=128, style={'input_type': 'password'})

class PersonSerializer(serializers.Serializer):
    id = serializers.IntegerField(label="ID", read_only=True)
    user = UserSerializer()
    name = serializers.CharField(max_length=200)
    gender = serializers.ChoiceField(choices=['M', 'F', 'T'])
    address = serializers.CharField(max_length=1000)
    work_phone = serializers.CharField(max_length=15, required=False, allow_null=True)
    home_phone = serializers.CharField(max_length=15, required=False, allow_null=True)
    mobile = serializers.CharField(max_length=15, required=False, allow_null=True)
    email = serializers.EmailField(required=False, allow_blank=True)
    date_of_birth = serializers.DateField()
    additional_document = serializers.ChoiceField(choices=['NO','DL', 'RC', 'PP'])
    document_number = serializers.CharField(max_length=10, required=False, allow_null=True)
    document_scan = serializers.FileField(max_length=1000, required=False, allow_null=True)
    photo = serializers.ImageField(required=False, allow_null=True)


class AdminSerializer(serializers.Serializer):
    id = serializers.IntegerField(label="ID", read_only=True)
    person = PersonSerializer()
    # More fields will be added later
user = UserSerializer(required=False)
每个序列化程序都定义了显式的create()和update()方法,为了简洁起见,我省略了这些方法。我可以看到这些没有被调用,因此在验证过程中可能会遇到错误

当我执行GET操作时,Person或AdminAPI端点将正确返回所有嵌套对象

当我对Person执行PUT或POST操作时,它接受可选字段中的空白输入。但是,如果在对管理对象执行PUT或POST操作时将相同的字段保留为空,则会按如下方式标记错误

class UserSerializer(serializers.Serializer):
    id = serializers.IntegerField(label='ID', read_only=True)
    username = serializers.CharField(max_length=30)
    password = serializers.CharField(max_length=128, style={'input_type': 'password'})

class PersonSerializer(serializers.Serializer):
    id = serializers.IntegerField(label="ID", read_only=True)
    user = UserSerializer()
    name = serializers.CharField(max_length=200)
    gender = serializers.ChoiceField(choices=['M', 'F', 'T'])
    address = serializers.CharField(max_length=1000)
    work_phone = serializers.CharField(max_length=15, required=False, allow_null=True)
    home_phone = serializers.CharField(max_length=15, required=False, allow_null=True)
    mobile = serializers.CharField(max_length=15, required=False, allow_null=True)
    email = serializers.EmailField(required=False, allow_blank=True)
    date_of_birth = serializers.DateField()
    additional_document = serializers.ChoiceField(choices=['NO','DL', 'RC', 'PP'])
    document_number = serializers.CharField(max_length=10, required=False, allow_null=True)
    document_scan = serializers.FileField(max_length=1000, required=False, allow_null=True)
    photo = serializers.ImageField(required=False, allow_null=True)


class AdminSerializer(serializers.Serializer):
    id = serializers.IntegerField(label="ID", read_only=True)
    person = PersonSerializer()
    # More fields will be added later
user = UserSerializer(required=False)
我的要求是:

{
    "id": 1,
    "person": {
        "id": 1,
        "user": {
            "id": 2,
            "username": "nina.sinha",
            "password": "pbkdf2_sha256$12000$CjmifxpP1DDv$1622S7enIwnT+NcwhMKIEWrq8Uy7gQQJPQQueML21Sg="
        },
        "name": "Nina Sinha",
        "gender": "F",
        "address": "1234, 6th Cross, 7th Main Street",
        "work_phone": "42011567",
        "home_phone": "",
        "mobile": "9854609658",
        "email": "nina.sinha@yahoo.com",
        "date_of_birth": "1985-04-03",
        "additional_document": "NO",
        "document_number": "",
        "document_scan": null,
        "photo": null
    }
}
错误:

HTTP 400 Bad Request
Content-Type: application/json
Vary: Accept
Allow: GET, PUT, PATCH, HEAD, OPTIONS

{
    "person": {
        "document_scan": [
            "The submitted data was not a file. Check the encoding type on the form."
        ],
        "photo": [
            "The submitted data was not a file. Check the encoding type on the form."
        ],
        "document_number": [
            "This field may not be blank."
        ],
        "user": [
            "This field is required."
        ],
        "home_phone": [
            "This field may not be blank."
        ]
    }
}
字段document\u scan、document\u number和home\u phone保留为空,但它们是可选字段,AdminSerializer应该接受这一点

已经输入了与用户相关的字段,但我仍然收到错误“此字段是必需的”,好像它们丢失了一样


我错过了什么?如果我使用ModelSerializer,我会面临同样的问题。

查看代码,为什么不使用ModelSerializer而不是serializer。在序列化程序级别,您可以根据需要更改字段。您可以将序列化程序中的必填字段更改为非必填字段,在模型级别上不会出现问题

序列化程序.py

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'password')

class PersonSerializer(serializers.ModelSerializer):
    user = UserSerializer()
    class Meta:
        model = Person
        fields = ('id', 'user', # specify other fields)

class AdminSerializer(serializers.ModelSerializer):
    person = PersonSerializer()
    class Meta:
        model = Admin
        fields = ('id', 'person', # specify other fields)
如果要在PersonSerializer中将用户字段更改为非必填字段,请按如下所示更改代码

class UserSerializer(serializers.Serializer):
    id = serializers.IntegerField(label='ID', read_only=True)
    username = serializers.CharField(max_length=30)
    password = serializers.CharField(max_length=128, style={'input_type': 'password'})

class PersonSerializer(serializers.Serializer):
    id = serializers.IntegerField(label="ID", read_only=True)
    user = UserSerializer()
    name = serializers.CharField(max_length=200)
    gender = serializers.ChoiceField(choices=['M', 'F', 'T'])
    address = serializers.CharField(max_length=1000)
    work_phone = serializers.CharField(max_length=15, required=False, allow_null=True)
    home_phone = serializers.CharField(max_length=15, required=False, allow_null=True)
    mobile = serializers.CharField(max_length=15, required=False, allow_null=True)
    email = serializers.EmailField(required=False, allow_blank=True)
    date_of_birth = serializers.DateField()
    additional_document = serializers.ChoiceField(choices=['NO','DL', 'RC', 'PP'])
    document_number = serializers.CharField(max_length=10, required=False, allow_null=True)
    document_scan = serializers.FileField(max_length=1000, required=False, allow_null=True)
    photo = serializers.ImageField(required=False, allow_null=True)


class AdminSerializer(serializers.Serializer):
    id = serializers.IntegerField(label="ID", read_only=True)
    person = PersonSerializer()
    # More fields will be added later
user = UserSerializer(required=False)

你能将你试图发送的post请求放入吗?内联编辑以添加put请求的内容。即使使用ModelSerializer,我也面临同样的问题。两级嵌套工作正常,但三级嵌套会抛出错误,抱怨字段丢失,即使我已经包含了字段,或者字段是可选的。我现在已经解决了这个问题,实现了AdminSerializer(包括PersonSerializer)的两级嵌套,并将用户作为Serializer.SlugRelatedField保留在PersonSerializer中。这似乎奏效了。