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)