所以我有以下结构:
ClientFile属于所有者(类名=联系人)。我正在尝试使用API创建Clientfile。该请求包含以下数据:
{
name: "Hello!"
owner: {
id: 1,
first_name: "Charlie",
last_name: "Watson"
}
}
我根据我的结构创建了序列化器。希望这个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'])
我确实进入了创建方法。但是,我需要(['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',
)
在Django REST Framework中,AutoField
字段(自动生成的字段)默认为只读。来自the docs:
read_only
将其设置为
True
以确保在序列化表示时使用该字段,但在反序列化期间创建或更新实例时不使用该字段。默认为
False
您可以通过在shell中打印表示来查看inspecting your serializer:
serializer = ClientfileSerializer()
print repr(serializer)
你可以通过在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}}
你可以尝试这样的事情:
class YourModelSerializer(serializers.ModelSerializer):
class Meta:
model = YourModel
fields = ('id', 'field1', 'field2')
def to_internal_value(self, data):
"""
Dict of native values <- Dict of primitive datatypes.
Add instance key to values if `id` present in primitive dict
:param data:
"""
obj = super(YourModelSerializer, self).to_internal_value(data)
instance_id = data.get('id', None)
if instance_id:
obj['instance'] = YourModel.objects.get(id=instance_id)
return obj
然后在序列化程序验证的数据中,如果request.data具有“id”键,则应该具有“instance”键。
您也可以只添加“id”而不是完整的实例/对象。
好吧,所以我发现了一种不同的方法。我为所有者关系添加了一个IntegerField序列化程序。我还必须将所有者关系设置为read_only = True。
这是我通过POST发送的json:
{
name: "Hello!"
owner_id: 1
}
这是我的序列化器:
class ClientfileSerializer(serializers.ModelSerializer):
owner_id = serializers.IntegerField()
owner = ContactSerializer(read_only=True)
class Meta():
model = Clientfile
fields = (
'id',
'owner_id',
'owner',
)
它看起来不像第一种方式那么酷,但它确实起到了作用。另外,我不想创建新的所有者,只需选择已存在于数据库中的所有者。因此,可能只有ID而不是通过Json发布的完整信息集更具语义性。