我想显示特定模型的所有对象,以及它的相关对象(面向对象)。 有没有办法更改/自定义 JSON 输出? (就键名、值还是嵌套而言?)
views.py
class QuestionSerializer(serializers.ModelSerializer):
choices = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Question
fields = '__all__'
serializers.py
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField(auto_now_add=True, editable=False, name='pub_date')
def __str__(self):
return self.question_text
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='choices')
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
def related_question(self):
q = self.question.question_text
return q
models.py
HTTP 200 OK
Allow: OPTIONS, GET
Content-Type: application/json
Vary: Accept
[
{
"id": 1,
"choices": [
1,
2,
3
],
"question_text": "Question 1",
"pub_date": "2020-12-19T23:07:25.071171+05:30"
},
{
"id": 2,
"choices": [
4,
5
],
"question_text": "Question 2",
"pub_date": "2020-12-21T13:58:37.595672+05:30"
}
]
输出
choices
在输出中,pk
显示对象的 choice_text
。
如何更改它以显示 depth
或自定义字符串?
另外,对象嵌套的方式可以自定义吗?
编辑:当我问是否有办法行使更多控制权时,我的意思是控制 JSON 响应的 git commit -m 'message here'
。
答案 0 :(得分:1)
考虑使用 SlugRelatedField
而不是 PrimaryKeyRelatedField
。例如:
class QuestionSerializer(serializers.ModelSerializer):
choices = SlugRelatedField(many=True, read_only=True, slug_field='choice_text')
class Meta:
model = Question
fields = '__all__'
此外,您需要使 choice_text
字段唯一,即添加 unique=True
以使其工作。
choice_text = models.CharField(max_length=200, unique=True)
仅供参考,您可以从模型定义中删除 __unicode__
方法。可以在此 Django documentation link 中找到说明。
答案 1 :(得分:1)
如果您希望更多地控制您希望返回的内容
,您可以使用serializers.SerializerMethodField(...)
class QuestionSerializer(serializers.ModelSerializer):
choices = serializers.SerializerMethodField()
def get_choices(self, question):
return [choice.choice_text for choice in question.choices.all()]
class Meta:
model = Question
fields = '__all__'
答案 2 :(得分:1)
您可以使用序列化程序的方法字段将 choices
键替换为您想要的任何相关模型字段。例如
class QuestionSerializer(serializers.ModelSerializer):
choices = serializers.SerializerMethodField('get_choices')
class Meta:
model = Question
fields = '__all__'
def get_choices(self, obj):
return obj.choices.values('choice_text').distinct() # or values('id', 'choice_text') based on your requirements
请注意,从性能角度(例如 [choice.choice_text for choice in question.choices.all()]
等)来看,值是比遍历所有对象更好的方法。
EDIT: SerializerMethodField
当我们想要运行一些自定义逻辑来填充特定字段时使用。
使用 ModelSerializer
时,source
关键字可用于访问字段(相关、非相关),甚至在与端点交互的人员需要不同名称的情况下重命名字段。
重命名示例(使用问题中提到的模型)
class QuestionSerializer(serializers.ModelSerializer):
poll_question = serializers.CharField(source='question_text')
class Meta:
model = Question
fields = '__all__'
获取 FK 相关字段的示例:
class ChoiceSerializer(serializers.ModelSerializer):
poll_question = serializers.CharField(source='question.question_text')
class Meta:
model = Choice
fields = '__all__'
This 是了解如何以及何时在 DRF 中使用 serializers
的非常好的基础读物。