pip install djangorestframework pip install markdown # Markdown support for the browsable API. pip install django-filter # Filtering support
'rest_framework',
pip3 install coreapi
REST_FRAMEWORK = { 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema', }
url(r'^docs/', include_docs_urls("运维平台接口文档"))前端
from rest_framework.documentation import include_docs_urls urlpatterns = [ path('docs/', include_docs_urls(title="运维平台API接口文档",description="django drf 接口文档")), ]
class Idc(models.Model): name = models.CharField("机房名称",max_length=32) address = models.CharField("机房地址",max_length=256) phone = models.CharField("联系人",max_length=15) email = models.EmailField("邮件地址",default="null") letter = models.CharField("IDC简称",max_length=5) def __str__(self): return self.name class Meta: db_table = 'resources_idc'
serializers.Serializer
不须要指定模型,须要序列化那些字段都须要显式指定,同时须要重写create
和update
方法django
class IdcSerializer(serializers.Serializer): """ Idc 序列化类 """ id = serializers.IntegerField(read_only=True) name = serializers.CharField(required=True, max_length=32, label="机房名称", help_text="机房名称", error_messages={"blank": "机房名称不能为空", "required": "这个字段为必要字段"}) address = serializers.CharField(required=True, max_length=256, label="机房地址", help_text="IDC详细地址", error_messages={"blank": "这个字段不能为空", "required": "这个字段为必要字段"} ) phone = serializers.CharField(required=True, max_length=15, label="联系电话", help_text="联系电话") email = serializers.EmailField(required=True, label="email", help_text="email地址") letter = serializers.CharField(required=True, max_length=5, label="字母简称", help_text="字母简称") def create(self, validated_data): return Idc.objects.create(**validated_data) def update(self, instance, validated_data): instance.name = validated_data.get("name", instance.name) instance.address = validated_data.get("address", instance.address) instance.phone = validated_data.get("phone", instance.phone) instance.email = validated_data.get("email", instance.email) instance.save() return instance
class IdcViewset(viewsets.ModelViewSet): queryset = Idc.objects.all() serializer_class = IdcSerializer
from django.urls import path,include from rest_framework.routers import DefaultRouter from idcs.views import IdcViewset router = DefaultRouter() router.register('idcs',IdcViewset,basename='idcs') urlpatterns = [ path('', include(router.urls)) ]
[ { "id": 1, "name": "亚太机房", "address": "神舟路999号", "phone": "13812345678", "email": "xxx@com.cn", "letter": "ytjf" }, { "id": 2, "name": "亚太机房1", "address": "神舟路999号1", "phone": "13812345678", "email": "xxx@com.cn", "letter": "ytjf1" }, { "id": 3, "name": "亚太机房2", "address": "神舟路999号2", "phone": "13812345678", "email": "xxx@com.cn", "letter": "ytjf2" } ]
class Cabinet(models.Model): idc = models.ForeignKey(Idc, verbose_name="所在机房",on_delete=models.CASCADE) name = models.CharField(max_length=255) def __str__(self): return self.name class Meta: db_table = "resources_cabinet" ordering = ["id"]
class CabinetSerializer(serializers.Serializer): idc = serializers.PrimaryKeyRelatedField(many=False, queryset=Idc.objects.all()) name = serializers.CharField(required=True)
class CabinetViewset(viewsets.ModelViewSet): queryset = Cabinet.objects.all() serializer_class = CabinetSerializer
create
方法,提交时报错,但能够正常显示# get [ { "idc": 1, "name": "A座6楼 13排2机柜" }, { "idc": 1, "name": "A座1楼 13排2机柜" }, { "idc": 1, "name": "A座2楼 13排2机柜" } ] # post Exception Value: `create()` must be implemented.
from idcs.serializers import IdcSerializer class CabinetSerializer(serializers.Serializer): idc = IdcSerializer(many=False) name = serializers.CharField(required=True)
显示以下api
[ { "idc": { "id": 1, "name": "亚太机房", "address": "神舟路999号", "phone": "13812345678", "email": "xxx@com.cn", "letter": "ytjf" }, "name": "A座6楼601 13排2机柜" } ]
from idcs.serializers import IdcSerializer class CabinetSerializer(serializers.Serializer): idc_name = serializers.SerializerMethodField() name = serializers.CharField(required=True) def get_idc_name(self,obj): return obj.idc.name
显示以下markdown
[ { "idc_name": "亚太机房", "name": "A座6楼601 13排2机柜" } ]
PrimaryKeyRelatedField
在to_representation
中进行额外字段的增长运维
class CabinetSerializer(serializers.Serializer): idc = serializers. PrimaryKeyRelatedField(many=False, queryset=Idc.objects.all()) name = serializers.CharField(required=True) def to_representation(self, instance): idc_obj = instance.idc ret = super(CabinetSerializer, self).to_representation(instance) ret["idc"] = { "id": idc_obj.id, "name": idc_obj.name } return ret
显示以下:post
[ { "idc": { "id": 1, "name": "亚太机房" }, "name": "A座6楼601 13排2机柜" } ]
反序列化的过程ui
前端提交数据 --> 数据存储在request的get、post、body中 --> drf经过to_internal_value获取原始的数据 --> 进入单独字段级别的验证 validated_字段 --> 所有字段验证(好比重复数据 validated)--> 进入表级别的验证
from idcs.serializers import IdcSerializer class CabinetSerializer(serializers.Serializer): idc = IdcSerializer(many=False) name = serializers.CharField(required=True) # 重写 create 方法 def create(self, validated_data): return Cabinet.objects.create(**validated_data)
序列化显式以下url
[ { "idc": { "id": 1, "name": "亚太机房", "address": "神舟路999号", "phone": "13812345678", "email": "xxx@com.cn", "letter": "ytjf" }, "name": "A座6楼601 13排2机柜" },
{ "idc": 1, "name": "A座3楼 13排2机柜" }
or key, value in self.value.items(): AttributeError: 'int' object has no attribute 'items'
{ "idc": { "id": 1, "name": "亚太机房", "address": "神舟路999号", "phone": "13812345678", "email": "xxx@com.cn", "letter": "ytjf" }, "name": "A座3楼601 13排2机柜" }
"Cabinet.idc" must be a "Idc" instance.
模型rest
class Cabinet(models.Model): idc = models.ForeignKey(Idc, verbose_name="所在机房",on_delete=models.CASCADE) name = models.CharField(max_length=255)
def validate(self, attrs): idc_data = attrs.pop('idc') idc_name = idc_data['name'] try: idc_inst = Idc.objects.get(name=idc_name) attrs['idc'] = idc_inst return attrs except Idc.DoesNotExist: raise serializers.ValidationError('机房%s不存在'%idc_name)
{ "idc": { "id": 1, "name": "亚太机房", "address": "神舟路999号", "phone": "13812345678", "email": "xxx@com.cn", "letter": "ytjf" }, "name": "A座3楼601 13排2机柜" }
for k,v in idc_data.items(): print(k,v) # 由于idc的模型 id 字段在序列化时是只读,反序列化时会被丢弃 # OrderedDict([('idc', OrderedDict([('name', '亚太机房'), ('address', '神舟路999号'), ('phone', '13812345678'), ('email', 'xxx@com.cn'), ('letter', 'ytjf')])), ('name', 'A座3楼601 13排2机柜')])
{ "idc": { "name": "亚太机房" }, "name": "A座4楼601 13排2机柜" } { "idc": { "address": [ "这个字段为必要字段" ], "phone": [ "This field is required." ], "email": [ "This field is required." ], "letter": [ "This field is required." ] } }
[ { "idc_name": "亚太机房", "name": "A座6楼601 13排2机柜" } ]
序列化显式以下,看起来和方法一的显示层级同样code
[ { "idc": { "id": 1, "name": "亚太机房" }, "name": "A座6楼601 13排2机柜" } ]
{ "idc": 1, "name": "A座4楼601 13排2机柜" }
{ "idc": { "id": 1, "name": "亚太机房" }, "name": "A座4楼601 13排2机柜" }
# 父表 class Idc(models.Model): name = models.CharField("机房名称",max_length=32) address = models.CharField("机房地址",max_length=256) phone = models.CharField("联系人",max_length=15) email = models.EmailField("邮件地址",default="null") letter = models.CharField("IDC简称",max_length=5) def __str__(self): return self.name class Meta: db_table = 'resources_idc' # 子表 class Cabinet(models.Model): idc = models.ForeignKey(Idc, verbose_name="所在机房",on_delete=models.CASCADE) name = models.CharField(max_length=255) def __str__(self): return self.name class Meta: db_table = "resources_cabinet" ordering = ["id"]
class CabinetSerializer(serializers.Serializer): idc = serializers.PrimaryKeyRelatedField(many=False, queryset=Idc.objects.all()) name = serializers.CharField(required=True) def to_representation(self, instance): idc_obj = instance.idc ret = super(CabinetSerializer, self).to_representation(instance) ret["idc"] = { "id": idc_obj.id, "name": idc_obj.name } return ret def create(self, validated_data): return Cabinet.objects.create(**validated_data)
idc = IdcSerializer(many=False)
指定父级序列化时,指定须要显示的字段,效果和方法3同样,反序列化时须要使用在 validate 进行外键字段的实例获取(捕获不存在时可修改成增长)def get_字段名(self,obj)
显示的字段能够与当前序列化的字段在同一个级别,若是须要显示多个字段,代码量稍微会多一点,外键字段不容许为null,则没法进行反序列化PrimaryKeyRelatedField
无论是 1:n n:1 n:n 均可以进行控制,在 to_representation
进行外键字段的序列化显式,反序列化时前端只须要正常传入外键的id值便可,推荐使用该方法全部的字段在序列化时能够更改显示名字
children = serializers.IntegerField(source='parent_group',required=False)