Capítulo previo:
Siguiente capítulo:
Documentación oficial:
Serializadores - Django REST framework
1. Informe de prueba, serializador de informes y vista
1.1 Serializador
aplicaciones/informes/serializadores.py
# -*- coding:utf-8 -*-
# @Author: 喵酱
# @time: 2023 - 06 -12
# @File: serializers.py
# desc:
from rest_framework import serializers
from .models import Reports
class ReportsModelSerilizer(serializers.ModelSerializer):
class Meta:
model = Reports
exclude = ('update_time',)
read_only_fields = ('name', 'count', 'result', 'success')
extra_kwargs = {
"create_time": {
"read_only": True,
"format": "%Y年%m月%d日 %H:%M:%S"
},
"name": {
"read_only": True,
},
"html": {
"write_only": True
},
"summary": {
"write_only": True
}
}
def to_representation(self, instance):
data = super().to_representation(instance)
data['result'] = '成功' if data.get('result') else '失败'
return data
1.1.1 Explicación del código:
1, exclude:
Puede establecer el exclude
atributo en una lista de campos que se excluirán del serializador.
Por ejemplo:
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
exclude = ['users']
2. read_only_fields = () establecer el atributo de campo en solo lectura
3. extra_kwargs = {}, establece los atributos del campo.
4. Campo personalizado to_representation
Documentación oficial: Campos de serializador - Django REST framework
Campos Personalizados
Si desea crear un campo personalizado, deberá crear una subclase Field
y luego anular uno o ambos métodos .to_representation()
y .to_internal_value()
. Estos dos métodos se utilizan para convertir entre el tipo de datos inicial y un tipo de datos serializable primitivo. Los tipos de datos primitivos normalmente serán cualquiera de un número, cadena, booleano, date
/ time
/ datetime
o None
. También pueden ser cualquier objeto similar a una lista o diccionario que solo contenga otros objetos primitivos. Es posible que se admitan otros tipos, según el renderizador que esté utilizando.
Se llama al .to_representation()
método para convertir el tipo de datos inicial en un tipo de datos serializable primitivo.
Se llama al .to_internal_value()
método para restaurar un tipo de datos primitivo en su representación interna de Python. Este método debería generar un serializers.ValidationError
si los datos no son válidos.
Campos personalizados
Si desea crear un campo personalizado, debe subclasificar el campo y anular uno o ambos métodos .to_representation() y .to_internal_value(). Estos dos métodos se utilizan para convertir entre el tipo de datos original y el tipo de datos serializable original. Los tipos de datos primitivos suelen ser números, cadenas, booleanos, fecha/hora/fechahora o Ninguno. También pueden ser cualquier objeto tipo lista o diccionario que solo contenga otros objetos primitivos. Es posible que se admitan otros tipos, según el renderizador que esté utilizando.
Llame al método .to_representation() para convertir el tipo de datos inicial en un tipo de datos primitivo serializable.
Llamar al método .to_internal_value() restaura el tipo de datos primitivo a su representación interna de Python. Este método debería elevar el serializador. Devuelve ValidationError si los datos no son válidos.
Ejemplos
Un campo personalizado básico
Veamos un ejemplo de serialización de una clase que representa un valor de color RGB:
class Color:
"""
A color represented in the RGB colorspace.
"""
def __init__(self, red, green, blue):
assert(red >= 0 and green >= 0 and blue >= 0)
assert(red < 256 and green < 256 and blue < 256)
self.red, self.green, self.blue = red, green, blue
class ColorField(serializers.Field):
"""
Color objects are serialized into 'rgb(#, #, #)' notation.
"""
def to_representation(self, value):
return "rgb(%d, %d, %d)" % (value.red, value.green, value.blue)
def to_internal_value(self, data):
data = data.strip('rgb(').rstrip(')')
red, green, blue = [int(col) for col in data.split(',')]
return Color(red, green, blue)
1.2 Ver
aplicaciones/informes/vistas.py
import logging
import json
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework import permissions
from rest_framework import mixins
from django.http.response import StreamingHttpResponse
from rest_framework.response import Response
from rest_framework import status
from . import serializers
from .models import Reports
from utils.pagination import PageNumberPagination
logger = logging.getLogger('miaostudydjango')
class ReportViewSet(mixins.ListModelMixin,
mixins.RetrieveModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
queryset = Reports.objects.all()
serializer_class = serializers.ReportsModelSerilizer
permission_classes = [permissions.IsAuthenticated]
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
try:
summary = json.loads(instance.summary, encoding='utf-8')
return Response({
'id': instance.id,
'summary': summary
}, status=status.HTTP_200_OK)
except Exception:
return Response({
'err': '测试报告summary格式有误'
}, status=status.HTTP_400_BAD_REQUEST)
@action(detail=True)
def download(self, request, *args, **kwargs):
# 1、获取html源码
instance = self.get_object()
# 2、将html源码转化为生成器对象
# byte_data = instance.html.encode('utf-8')
byte_data = instance.html
# 3、StreamingHttpResponse对象
response = StreamingHttpResponse(iter(byte_data))
# StreamingHttpResponse、HttpResponse、Response,这些['key'] = 'value',可以添加响应头数据
response['Content-Type'] = 'application/octet-stream'
response['Content-Disposition'] = f"attachment; filename*=UTF-8 '' {instance.name + '.html'}"
return response
1.2.1 Explicación del código
1.3 Enrutamiento
aplicaciones/informes/urls.py
from rest_framework import routers
from . import views
router = routers.SimpleRouter()
router.register(r'reports', views.ReportViewSet)
urlpatterns = [
]
urlpatterns += router.urls
miaostudydjango/urls.py
urlpatterns = [
path('', include('reports.urls')),
]