Django REST Framework嵌套资源键"id"无法访问

Mon*_*nja 13 python django django-rest-framework

所以我有以下结构:

ClientFile属于所有者(类名=联系人).我正在尝试使用API​​创建Clientfile.该请求包含以下数据:

{
  name: "Hello!"
  owner: {
    id: 1,
    first_name: "Charlie",
    last_name: "Watson"
  }
}
Run Code Online (Sandbox Code Playgroud)

我根据我的结构创建了序列化器.希望这个API调用会创建一个名为"Hello!"的客户端文件.并联系ID 1作为所有者:

class ContactSerializer(serializers.ModelSerializer):
  class Meta:
    model = Contact
    fields = (
      'id',
      'first_name',
      'last_name',
    )

class ClientfileSerializer(serializers.ModelSerializer):

  owner = ContactSerializer(read_only=False)

  class Meta():
    model = Clientfile
    fields = (
      'id',
      'name',
      'owner',
    )

  def create(self, validated_data):

    owner = Contact.objects.get(pk=validated_data['owner']['id'])
Run Code Online (Sandbox Code Playgroud)

我确实进入了创建方法.但是,我需要的唯一字段(['owner']['id'])无法访问.如果我这样做print ['owner']['first_name'],确实会返回'查理'.但由于某些原因,ID似乎无法访问...

有什么理由可以发生这种情况?我错过了什么吗?(我是Django的新手)


解决方案:刚刚发现ID首先没有显示的原因是因为我必须在这样的字段中声明它:希望这会有所帮助.

class ContactSerializer(serializers.ModelSerializer):

  id = serializers.IntegerField() # ? Here

  class Meta:
    model = Contact
    fields = (
      'id',
      'first_name',
      'last_name',
    )
Run Code Online (Sandbox Code Playgroud)

br3*_*3w5 12

在Django中,REST Framework AutoField字段(自动生成的字段)默认为只读.来自文档:

read_only

将其设置True为确保在序列化表示时使用该字段,但在反序列化期间创建或更新实例时不使用该字段.

默认为 False

您可以通过在shell中打印表示来检查序列化程序,从而看到这一点:

serializer = ClientfileSerializer()
print repr(serializer)
Run Code Online (Sandbox Code Playgroud)

您可以通过设置以下内容read_only=False中的id字段来覆盖它extra_kwargs:

class ContactSerializer(serializers.ModelSerializer):
  class Meta:
    model = Contact
    fields = (
      'id',
      'first_name',
      'last_name',
    )
    extra_kwargs = {'id': {'read_only': False}}

class ClientfileSerializer(serializers.ModelSerializer):

  owner = ContactSerializer(read_only=False)

  class Meta():
    model = Clientfile
    fields = (
      'id',
      'name',
      'owner',
    )
    extra_kwargs = {'id': {'read_only': False}}
Run Code Online (Sandbox Code Playgroud)


Mon*_*nja 4

好吧,所以我找到了一种有效的不同方法。我为所有者关系添加了一个 IntegerField 序列化器。我还必须将所有者关系设置为 read_only=True。

这是我通过 POST 发送的 json:

{
  name: "Hello!"
  owner_id: 1
}
Run Code Online (Sandbox Code Playgroud)

这是我的序列化器:

class ClientfileSerializer(serializers.ModelSerializer):

  owner_id = serializers.IntegerField()
  owner = ContactSerializer(read_only=True)

  class Meta():
    model = Clientfile
    fields = (
      'id',
      'owner_id',
      'owner',
    )
Run Code Online (Sandbox Code Playgroud)

它看起来不如第一种方式酷,但它可以完成工作。另外,我不想创建新的所有者,而只是选择数据库中已有的所有者。因此,也许只有 ID 而没有通过 Json 发布的完整信息集更符合语义。