DRF 获取 OneToOne 模型的所有字段
DRF Get All Fields of OneToOne Model
我对 DRF 比较陌生,目前遇到了一个问题。经过多次试验,我试着环顾四周,但找不到我想要的东西。如果这个问题已经得到回答,请直接告诉我原来的问题。在此先感谢您的帮助!
问题:
我有一个与用户模型具有一对一关系的配置文件模型。当我创建一个新的用户对象时,配置文件对象会按预期自动创建。我想创建一个 API,这样当我像 api/profile/
一样执行它时,除了 return 配置文件模型字段外,它还应该 return 用户模型中的所有字段即 first_name
、last_name
、username
、email
等...
class Profile(models.Model):
rater = models.OneToOneField(User, on_delete=models.CASCADE, related_name='approval')
certified = models.ManyToManyField(Protocol, blank=True, default=None, related_name='trained')
is_approved = models.BooleanField(default=False)
我的ProfileSerializer如下:
class ProfileSerializer(serializers.ModelSerializer):
approval = UserSerializer(read_only=True)
class Meta:
model = Profile
fields = '__all__'
当我 运行 API 我得到以下响应:
[
{
"id": 1,
"rater": 3,
"certified": [],
"is_approved": false
}
]
如何获得以下响应:
[
{
"id": 1,
"rater": 3,
"certified": [],
"is_approved": false,
"first_name": xyz,
"last_name": abc,
"username": 123,
"email": abc@gmail.com,
}
]
尝试将 approval
更改为 rater
:
class ProfileSerializer(serializers.ModelSerializer):
rater = UserSerializer(read_only=True)
class Meta:
model = Profile
fields = '__all__'
这将自动从 Profile
中获取 rater
字段并将其传递给 UserSerializer
。
这样你最终会得到:
[
{
"id": 1,
"certified": [],
"is_approved": false,
"rater": {
"id": 3,
"first_name": "xyz",
"last_name": "abc",
"username": "123",
"email": "abc@gmail.com"
}
}
]
您可以通过几种方式做到这一点。最好的方法是制作一个包含来自两个模型的字段的序列化程序。您所拥有的很接近,但是因为您的相关字段名称在关系的配置文件端是 rater
。 (例如,您使用 profile.rater.email
,而不是 profile.approval
)
您应该使用名称 rater
或指定 source
关键字参数。
class ProfileSerializer(serializers.ModelSerializer):
approval = UserSerializer(read_only=True, source='rater')
class Meta:
model = Profile
fields = '__all__'
如果您希望结果是扁平的,而不是嵌套的,您可以指定一个 to_representation
方法。
def to_representation(self, instance):
# get the usual response as a dictionary
representation = super().to_representation(instance)
# pop the nested field and flatten
user_details = representation.pop('approval')
representation.update(user_details)
return representation
您也可以 'cheat' 并完全从 to_representation
方法直接执行此操作,尽管它需要更冗长一点并且您无法从 UserSerializer 中获得所有定义的优势。但如果您没有序列化程序并且出于某种原因不想制作序列化程序,这可能会有用。
def to_representation(self, instance):
representation = super().to_representation(instance)
user = instance.rater
representation.update({'email': user.email,
'first_name', user.first_name,
...
})
return representation
我对 DRF 比较陌生,目前遇到了一个问题。经过多次试验,我试着环顾四周,但找不到我想要的东西。如果这个问题已经得到回答,请直接告诉我原来的问题。在此先感谢您的帮助!
问题:
我有一个与用户模型具有一对一关系的配置文件模型。当我创建一个新的用户对象时,配置文件对象会按预期自动创建。我想创建一个 API,这样当我像 api/profile/
一样执行它时,除了 return 配置文件模型字段外,它还应该 return 用户模型中的所有字段即 first_name
、last_name
、username
、email
等...
class Profile(models.Model):
rater = models.OneToOneField(User, on_delete=models.CASCADE, related_name='approval')
certified = models.ManyToManyField(Protocol, blank=True, default=None, related_name='trained')
is_approved = models.BooleanField(default=False)
我的ProfileSerializer如下:
class ProfileSerializer(serializers.ModelSerializer):
approval = UserSerializer(read_only=True)
class Meta:
model = Profile
fields = '__all__'
当我 运行 API 我得到以下响应:
[
{
"id": 1,
"rater": 3,
"certified": [],
"is_approved": false
}
]
如何获得以下响应:
[
{
"id": 1,
"rater": 3,
"certified": [],
"is_approved": false,
"first_name": xyz,
"last_name": abc,
"username": 123,
"email": abc@gmail.com,
}
]
尝试将 approval
更改为 rater
:
class ProfileSerializer(serializers.ModelSerializer):
rater = UserSerializer(read_only=True)
class Meta:
model = Profile
fields = '__all__'
这将自动从 Profile
中获取 rater
字段并将其传递给 UserSerializer
。
这样你最终会得到:
[
{
"id": 1,
"certified": [],
"is_approved": false,
"rater": {
"id": 3,
"first_name": "xyz",
"last_name": "abc",
"username": "123",
"email": "abc@gmail.com"
}
}
]
您可以通过几种方式做到这一点。最好的方法是制作一个包含来自两个模型的字段的序列化程序。您所拥有的很接近,但是因为您的相关字段名称在关系的配置文件端是 rater
。 (例如,您使用 profile.rater.email
,而不是 profile.approval
)
您应该使用名称 rater
或指定 source
关键字参数。
class ProfileSerializer(serializers.ModelSerializer):
approval = UserSerializer(read_only=True, source='rater')
class Meta:
model = Profile
fields = '__all__'
如果您希望结果是扁平的,而不是嵌套的,您可以指定一个 to_representation
方法。
def to_representation(self, instance):
# get the usual response as a dictionary
representation = super().to_representation(instance)
# pop the nested field and flatten
user_details = representation.pop('approval')
representation.update(user_details)
return representation
您也可以 'cheat' 并完全从 to_representation
方法直接执行此操作,尽管它需要更冗长一点并且您无法从 UserSerializer 中获得所有定义的优势。但如果您没有序列化程序并且出于某种原因不想制作序列化程序,这可能会有用。
def to_representation(self, instance):
representation = super().to_representation(instance)
user = instance.rater
representation.update({'email': user.email,
'first_name', user.first_name,
...
})
return representation