Django Rest Framework - 嵌套字段:不要创建,而是从现有记录中获取一个

时间:2015-05-15 18:05:01

标签: django nested django-rest-framework

我们说我有一个约会模型。预约有医生和病人。 在创建约会时,用户选择医生和患者。这意味着只创建了实际的约会。不是博士和病人。

从数据库中检索约会时,我希望表示如下所示:

{
  id: 1,
  doctor: {
    id: 8,
    name: 'Dr James Brown',
    phone: '107-102-304',
  },
  patient: {
    id: 4,
    name: 'Mr Elvis',
    phone: '123-456'
  }
}

所以我的序列化器看起来像:

class AppointmentSerializer(serializers.ModelSerializer):

  id            = serializers.IntegerField(read_only=True)
  doctor        = ContactSerializer()
  patient       = ContactSerializer()

  class Meta:
    model  = Appointment
    fields = (
      'id',
      'doctor',
      'patient',
    )

我希望能够使用相同的序列化程序创建约会。这意味着我将POST到服务器的JSON看起来像这样(它基本上与上面相同,没有id字段,因为它是一个新记录):

{
  doctor: {
    id: 9,
    name: 'Dr Otis Redding',
    phone: '107-102-304'
  },
  patient: {
    id: 4,
    name: 'Mr Ray Charles',
    phone: '123-456'
  }
}

我将选项read_only = False添加到我的序列化程序(这应该使字段可写):

  doctor        = ContactSerializer(read_only=False)
  patient       = ContactSerializer(read_only=False)

但这会引发错误:

  

无法指定" OrderedDict([(' id',14),(u' name',   你好,约瑟芬'),(你'电话',你' 0123-456')])":"约会。医生"必须是"联系"   实例

我希望能够告诉Django-Rest-Framework:"不要创建医生和患者,但要通过id"选择它们。我知道在创建约会时没有必要发送整个表示。只有实际的ID是必要的。但同样,我这样做是因为我想使用相同的序列化程序并保持代码清洁。

这有意义吗?这是DRF的方式吗?

Ps:我注意到当关系为many = True时它会起作用。在我的情况下,预约只有一名医生和一名患者。

提前致谢。

1 个答案:

答案 0 :(得分:2)

好的,这就是我最终做的事情,以防它对某人有用:

import {Component, View, bootstrap} from 'angular2/angular2';
import {MdInput, MdInputContainer} from 'angular2_material/material';

// Defines a new HTML tag <hello-ngconf>
@Component({
    selector: 'material-demo'
})
@View({
    template: `
    <md-input-container>
      <label>Your name</label>
      <input #newname />
    </md-input-container>
    <p>
      Hello, {{newname.value}}
    </p>
    `,
    directives: [MdInputContainer, MdInput]
})
class MaterialDemoComponent {
}

bootstrap(MaterialDemoComponent);

class ContactField(serializers.Field):

  def to_internal_value(self, data)
    return Contact.objects.get(pk=data.get('id'))

  def to_representation(self, obj):
    return ContactSerializer(obj).data