我有两个模型来代表一个学生及其联系人。
class Contact(models.Model):
phone_num = models.IntegerField()
email = models.TextField()
class Student(models.Model):
name = models.TextField()
age = models.IntegerField()
contact = models.ForeignKey(Contact)
我需要返回的数据结构:
{
name: 'Peter',
age: 18,
contact: {
phone_num: 1234567890,
email: 'peter123@gmail.com'
}
}
在我的发布请求中,我收到json格式的数据:
{
name: 'Mary',
age: 19,
phone_num: 9876543210,
email: mary987@gmail.com
}
我正在尝试创建用于数据验证的序列化器。
联系方式:
class ContactSerializer(ModelSerializer):
class Meta:
model = Contact
exclude = ('id',)
学生:
class StudentSerializer(ModelSerializer):
contact = ContactSerializer()
class Meta:
model = Student
exclude = ('id',)
我试图将请求后的数据放入序列化器中,并检查其是否有效。
data = {
name: 'Mary',
age: 19,
phone_num: 9876543210,
email: mary987@gmail.com
}
student = StudentSerializer(data=data)
student.is_valid()
// It returns false.
print(student.errors)
// Print: {'contact': [ErrorDetail(string='This field is required.', code='required')]}
如何使用此数据结构验证我的数据?
答案 0 :(得分:0)
它表示contact
是必填字段。如果您想在数据中传递联系人ID,
像下面这样写,
class StudentSerializer(ModelSerializer):
contact = ContactSerializer(read_only=True)
class Meta:
model = Student
exclude = ('id',)
def create(self, attrs):
instance = super(StudentSerializer, self).create(attrs)
instance.contact = self.initial_data.get('contact')
instance.save()
答案 1 :(得分:0)
简单的解决方案是将输入json有效负载的结构更改为嵌套形式,例如
{
"name": "Peter",
"age": 18,
"contact": {
"phone_num": 1234567890,
"email": "peter123@gmail.com"
}
}
如下更改您的序列化器,
class StudentSerializer(serializers.ModelSerializer):
contact = ContactSerializer(read_only=True)
phone_num = serializers.IntegerField(write_only=True)
email = serializers.EmailField(write_only=True)
def create(self, validated_data):
contact = Contact.objects.create(phone_num=validated_data.pop('phone_num'),
email=validated_data.pop('email'))
return Student.objects.create(**validated_data, contact=contact)
class Meta:
model = Student
exclude = ('id',)
为您的序列化器添加两个额外的字段,phone_num
和email
作为 write_only=True
,并使您的ContactSerializer
仅准备就绪,这将绕过序列化程序验证。
因此,我们需要一个自定义的创建方法。因此,请覆盖 create()
方法。
示例(方法2)
In [3]: data = {
...: 'name': 'Mary',
...: 'age': 19,
...: 'phone_num': 9876543210,
...: 'email': 'mary987@gmail.com'
...: }
In [4]: student = StudentSerializer(data=data)
In [5]: student.is_valid()
Out[5]: True
In [6]: student.save() # creates new student method
Out[6]: <Student: Student object>
In [7]: student.data
Out[7]: {'contact': OrderedDict([('phone_num', 9876543210), ('email', 'mary987@gmail.com')]), 'name': 'Mary', 'age': 19}
答案 2 :(得分:0)
您必须首先在联系表中创建数据,因为学生将其用作外键。 方便的方法之一就是以这种格式接收json
0 0 0
在您的views.py
`
{
name: 'Mary',
age: 19,
contact: {
phone_num: 9876543210,
email: mary987@gmail.com
}
}
`
在serializers.py
中context = {
phone_num: 9876543210,
email: mary987@gmail.com
}
serializer = ContactSerializer(data=request.data['contact'))
if serializer.is_valid():
serializer.save #saved contact data first
data = request.data
data['contact']=serializer.data['id']
serializer = StudentSerializer(data=data)
if serializer.is_valid():
serializer.save
return Response(serializer.data)
您要隐藏ID字段有什么具体说明吗?