如何从 django rest 框架中的模型制作自定义序列化程序?
How to make custom serializer from model in django rest framework?
我想从模型制作自定义序列化程序。
我想要这样的输出:
{
'name': {
'value': 'field value from model',
'type': 'String', # 'what the model field type like: String'
},
'number': {
'value': 'field value from model',
'type': 'Number', # 'what the model field type like: Number'
},
'type': {
'value': 'field value from model',
'type': 'Choice', # 'what the model field type like: Choice'
'options': ['Paved', 'UnPaved']
},
'category': {
'value': 'field value from model',
'type': 'Choice', # 'what the model field type like: Choice'
'options': ['primary', 'secondary']
},
'width': {
'value': 'field value from model',
'type': 'Number', # 'what the model field type like: Number'
}
}
这是我的模型:
class Road(models.Model):
name = models.CharField(max_length=250, null=True)
number = models.CharField(max_length=200, null=True)
type = models.CharField(max_length=100, null=True)
category = models.CharField(max_length=200, null=True)
width = models.FloatField(null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
这是序列化程序代码:
class RoadSerializer(serializers.ModelSerializer):
class Meta:
model = Road
exclude = ['created', 'updated']
视图如下:
@api_view(['GET'])
def get_road(request, pk=None):
queryset = Road.objects.all()
road= get_object_or_404(queryset, pk=pk)
serializer = RoadSerializer(road)
return Response(serializer.data)
把URL像这样
path(r'view/list/<pk>', views.get_road, name='road')
如何实现该输出?
哪种类型的序列化程序最适合获得这种输出?
非常感谢您提供的任何帮助。
实现此目的的一种方法是对所有自定义字段使用 SerializerMethodField(),类似于以下代码:
class RoadSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField()
number = serializers.SerializerMethodField()
type = serializers.SerializerMethodField()
category = serializers.SerializerMethodField()
width = serializers.SerializerMethodField()
class Meta:
model = Road
fields = (
"name",
"number",
"type",
"category",
"width",
)
exclude = ['created', 'updated']
def get_name(self, road)
return {
'value': road.name,
'type': 'String',
}
def get_number(selft, road)
return {
'value': road.number,
'type': 'Number',
}
def get_type(self, road)
return {
'value': road.type,
'type': 'Choice',
'options': ['Paved', 'UnPaved']
}
def get_category(self, road)
return {
'value': road.category,
'type': 'Choice',
'options': ['primary', 'secondary']
}
def get_width(self, road)
return {
'value': road.width,
'type': 'Number',
}
您可以覆盖 .to_representation()
序列化程序。你可以从这个开始:
class RoadSerializer(serializer.ModelSerializer):
# ...
def to_representation(self, obj):
base_representation = super().to_representation(obj)
fields = self.get_fields()
new_representation = OrderedDict()
for field_name, value in base_representation.items():
field = fields.get(field_name, None)
parsed_value = {
'value': value,
}
if field:
parsed_value['type'] = field.__class__.__name__
if isinstance(field, serializers.ChoiceField):
parsed_value['options'] = field.choices
new_representation[field_name] = parsed_value
return new_representation
我只是简化了此答案中每个字段的解析 type
。您可以调整它以使用将序列化程序字段映射到特定字符串的函数。
虽然您可能必须为每个需要自定义输出的序列化程序执行此操作,但是您仍然保留序列化程序的其他功能(如 .create()
、.update()
)。
我想从模型制作自定义序列化程序。
我想要这样的输出:
{
'name': {
'value': 'field value from model',
'type': 'String', # 'what the model field type like: String'
},
'number': {
'value': 'field value from model',
'type': 'Number', # 'what the model field type like: Number'
},
'type': {
'value': 'field value from model',
'type': 'Choice', # 'what the model field type like: Choice'
'options': ['Paved', 'UnPaved']
},
'category': {
'value': 'field value from model',
'type': 'Choice', # 'what the model field type like: Choice'
'options': ['primary', 'secondary']
},
'width': {
'value': 'field value from model',
'type': 'Number', # 'what the model field type like: Number'
}
}
这是我的模型:
class Road(models.Model):
name = models.CharField(max_length=250, null=True)
number = models.CharField(max_length=200, null=True)
type = models.CharField(max_length=100, null=True)
category = models.CharField(max_length=200, null=True)
width = models.FloatField(null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
这是序列化程序代码:
class RoadSerializer(serializers.ModelSerializer):
class Meta:
model = Road
exclude = ['created', 'updated']
视图如下:
@api_view(['GET'])
def get_road(request, pk=None):
queryset = Road.objects.all()
road= get_object_or_404(queryset, pk=pk)
serializer = RoadSerializer(road)
return Response(serializer.data)
把URL像这样
path(r'view/list/<pk>', views.get_road, name='road')
如何实现该输出? 哪种类型的序列化程序最适合获得这种输出?
非常感谢您提供的任何帮助。
实现此目的的一种方法是对所有自定义字段使用 SerializerMethodField(),类似于以下代码:
class RoadSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField()
number = serializers.SerializerMethodField()
type = serializers.SerializerMethodField()
category = serializers.SerializerMethodField()
width = serializers.SerializerMethodField()
class Meta:
model = Road
fields = (
"name",
"number",
"type",
"category",
"width",
)
exclude = ['created', 'updated']
def get_name(self, road)
return {
'value': road.name,
'type': 'String',
}
def get_number(selft, road)
return {
'value': road.number,
'type': 'Number',
}
def get_type(self, road)
return {
'value': road.type,
'type': 'Choice',
'options': ['Paved', 'UnPaved']
}
def get_category(self, road)
return {
'value': road.category,
'type': 'Choice',
'options': ['primary', 'secondary']
}
def get_width(self, road)
return {
'value': road.width,
'type': 'Number',
}
您可以覆盖 .to_representation()
序列化程序。你可以从这个开始:
class RoadSerializer(serializer.ModelSerializer):
# ...
def to_representation(self, obj):
base_representation = super().to_representation(obj)
fields = self.get_fields()
new_representation = OrderedDict()
for field_name, value in base_representation.items():
field = fields.get(field_name, None)
parsed_value = {
'value': value,
}
if field:
parsed_value['type'] = field.__class__.__name__
if isinstance(field, serializers.ChoiceField):
parsed_value['options'] = field.choices
new_representation[field_name] = parsed_value
return new_representation
我只是简化了此答案中每个字段的解析 type
。您可以调整它以使用将序列化程序字段映射到特定字符串的函数。
虽然您可能必须为每个需要自定义输出的序列化程序执行此操作,但是您仍然保留序列化程序的其他功能(如 .create()
、.update()
)。