HAdmin后端對DRF封裝
我想實現(xiàn)一個這樣的理想國:
比xadmin漂亮;比xadmin強大胃碾;前后端分離;基于Django和DRF涂屁;智能化配置书在。
以上幾點,是我們對HAdmin的設(shè)想拆又,設(shè)想這樣的后端能夠相對自動化輸出接口儒旬,讓前端能夠根據(jù)配置文件認識輸出的標準數(shù)據(jù)結(jié)構(gòu),從而進行渲染帖族。
于是栈源,初步版本的HAdmin上線了。
快速開始
安裝
pip install hadmin
使用方式
from rest_framework import viewsets
from hadmin import mixins
class CustomConfigViewSet(mixins.PageConfigMixin, viewsets.GenericViewSet):
list_class = CustomListSerializer
filter_class = CustomFilter
create_class = CustomCreateSerializer
read_class = CustomReadSerializer
extra = {}
其實竖般,就是用HAdmin下的mixins替代rest_framework下的mixins
并且甚垦,增加了一個PageConfigMixin方法,這個方法包含了四種配置文件的輸出方式涣雕,分別是:
list_class 列表的配置信息
filter_class 篩選器的配置信息
create_class 創(chuàng)建數(shù)據(jù)表單的配置信息
read_class 讀取最終數(shù)據(jù)的配置信息
extra 是額外擴展的數(shù)據(jù)艰亮,可以是字典或者列表等任意可以轉(zhuǎn)換成json的值,會原樣遞送到前端挣郭,用于前端渲染特殊情況下使用迄埃,非必填,根據(jù)需要使用
每個對應(yīng)的都是序列化器的的類兑障,序列化器建議每個方法用不同類侄非,這樣可以自由定義。
每個序列化器類的元數(shù)據(jù)可以增加一個custom字典流译,以便進行解析逞怨。
輸出到前端的數(shù)據(jù)樣例:
{
"filter": {
"base": [
{
"label": "手機號",
"method": "input",
"default": "",
"url": "",
"limit": 1,
"span": 6,
"key": "mobile"
},
{
"label": "姓名",
"method": "input",
"default": "",
"url": "",
"limit": 1,
"span": 6,
"key": "name"
},
{
"label": "姓名",
"method": "input",
"default": "",
"url": "",
"limit": 1,
"span": 6,
"key": "desc"
},
{
"label": "新房客源",
"method": "select",
"default": "",
"url": "",
"limit": 1,
"span": 6,
"key": "new",
"options": [
{
"id": "-1000",
"title": "不限"
},
{
"id": "true",
"title": "是"
},
{
"id": "false",
"title": "否"
},
{
"id": "isnull",
"title": "未填寫"
}
]
},
{
"label": "二手房客源",
"method": "select",
"default": "",
"url": "",
"limit": 1,
"span": 6,
"key": "old",
"options": [
{
"id": "-1000",
"title": "不限"
},
{
"id": "true",
"title": "是"
},
{
"id": "false",
"title": "否"
},
{
"id": "isnull",
"title": "未填寫"
}
]
},
{
"label": "租房客源",
"method": "select",
"default": "",
"url": "",
"limit": 1,
"span": 6,
"key": "rent",
"options": [
{
"id": "-1000",
"title": "不限"
},
{
"id": "true",
"title": "是"
},
{
"id": "false",
"title": "否"
},
{
"id": "isnull",
"title": "未填寫"
}
]
}
],
"adv": [ ],
"height": 100,
"fields": {
"mobile": "",
"name": "",
"desc": "",
"new": "",
"old": "",
"rent": ""
}
},
"create": {
"fields": {
"master": null,
"region": null,
"admins": [ ],
"mobile": "",
"name": "",
"new": false,
"old": false,
"rent": false,
"desc": ""
},
"detail": [
{
"label": "主理人",
"help_text": null,
"field_name": "master",
"required": true,
"type": "PrimaryKeyRelatedField",
"choices": [
{
"id": "1",
"title": "hofeng"
},
{
"id": "13",
"title": "18961330033"
},
{
"id": "83",
"title": "shanghai001"
},
{
"id": "84",
"title": "shanghai002"
},
{
"id": "85",
"title": "shanghai003"
},
{
"id": "86",
"title": "suqian001"
}
]
},
{
"label": "地區(qū)",
"help_text": null,
"field_name": "region",
"required": true,
"type": "PrimaryKeyRelatedField",
"choices": [
{
"id": "1",
"title": "上海【310000】"
},
{
"id": "21",
"title": "宿遷【321300】"
},
{
"id": "34",
"title": "鹽城【320900】"
}
]
},
{
"label": "協(xié)作人",
"help_text": null,
"field_name": "admins",
"required": true,
"type": "ManyRelatedField",
"choices": [
{
"id": "1",
"title": "hofeng"
},
{
"id": "13",
"title": "18961330033"
},
{
"id": "83",
"title": "shanghai001"
},
{
"id": "84",
"title": "shanghai002"
},
{
"id": "85",
"title": "shanghai003"
},
{
"id": "86",
"title": "suqian001"
}
]
},
{
"label": "手機號",
"help_text": "客源手機號",
"field_name": "mobile",
"required": true,
"type": "CharField"
},
{
"label": "姓名",
"help_text": null,
"field_name": "name",
"required": false,
"type": "CharField"
},
{
"label": "新房客源",
"help_text": null,
"field_name": "new",
"required": false,
"type": "BooleanField"
},
{
"label": "二手房客源",
"help_text": null,
"field_name": "old",
"required": false,
"type": "BooleanField"
},
{
"label": "租房客源",
"help_text": null,
"field_name": "rent",
"required": false,
"type": "BooleanField"
},
{
"label": "簡要說明",
"help_text": null,
"field_name": "desc",
"required": false,
"type": "CharField",
"base_template": "textarea.html"
}
]
},
"list": [
{
"label": "ID",
"field_name": "id",
"type": "IntegerField",
"width": "80"
},
{
"label": "手機號",
"field_name": "mobile",
"type": "CharField"
},
{
"label": "姓名",
"field_name": "name",
"type": "CharField"
},
{
"label": "主理人",
"field_name": "master",
"type": "StringRelatedField"
},
{
"label": "新房客源",
"field_name": "new",
"type": "BooleanField"
},
{
"label": "二手房客源",
"field_name": "old",
"type": "BooleanField"
},
{
"label": "租房客源",
"field_name": "rent",
"type": "BooleanField"
},
{
"label": "添加時間",
"field_name": "add_time",
"type": "DateTimeField"
}
],
"read": [
{
"label": "主理人",
"field_name": "master",
"type": "StringRelatedField"
},
{
"label": "地區(qū)",
"field_name": "region",
"type": "StringRelatedField"
},
{
"label": "協(xié)作人",
"field_name": "admins",
"type": "ManyRelatedField"
},
{
"label": "添加時間",
"field_name": "add_time",
"type": "DateTimeField"
},
{
"label": "手機號",
"field_name": "mobile",
"type": "CharField"
},
{
"label": "姓名",
"field_name": "name",
"type": "CharField"
},
{
"label": "新房客源",
"field_name": "new",
"type": "BooleanField"
},
{
"label": "二手房客源",
"field_name": "old",
"type": "BooleanField"
},
{
"label": "租房客源",
"field_name": "rent",
"type": "BooleanField"
},
{
"label": "簡要說明",
"field_name": "desc",
"type": "CharField"
}
]
}
下面是具體的使用方法
list_class
class CustomListSerializer(serializers.ModelSerializer):
master = serializers.StringRelatedField()
add_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S')
class Meta:
model = Custom
fields = ["id", "mobile", "name", "master", "new", "old", "rent", "add_time"]
custom = {
"id": {'width': '80'}
}
這是一個典型的列表讀取的序列化器福澡,元數(shù)據(jù)中規(guī)定的輸出字段叠赦,新增的custom字典表明某個字段的特別約定。
字典的健名用字段名表示定義某個字段革砸;
value值是一個字典除秀,健名自己定義窥翩,反饋到前端后,前端方便進行解析鳞仙。
建議保留width,label這類字段笔时,總之棍好,這里定義什么,前端就會收到什么允耿,然后前端進行渲染借笙。
輸出到前端后,對應(yīng)參數(shù)健名為:list
filter_class
作為篩選器较锡,要定義每個篩選項业稼,這是沒辦法避免的,例如:
class CustomFilter(django_filters.rest_framework.FilterSet):
mobile = django_filters.CharFilter(method='keyword_filter', help_text="手機號")
name = django_filters.CharFilter(method='keyword_filter', help_text="姓名")
desc = django_filters.CharFilter(method='keyword_filter', help_text="說明")
new = django_filters.BooleanFilter(method='common_filter', help_text="新房客源", label={'options': get_easy_bool()})
old = django_filters.BooleanFilter(method='common_filter', help_text="二手房客源", label={'options': get_easy_bool()})
rent = django_filters.BooleanFilter(method='common_filter', help_text="租房客源", label={'options': get_easy_bool()})
以上就是對篩選器的定義蚂蕴,對項的定義低散,放在label進行定義,選擇類的給options值骡楼,help_text是顯示出來的名稱
輸出到前端后熔号,對應(yīng)參數(shù)健名為:filter
create_class
創(chuàng)建類的輸出,是為了前端自動構(gòu)造提交表單而定鸟整,序列化器寫法沒有特別引镊,和list一樣,可以在元數(shù)據(jù)中增加一個custom字典篮条,對應(yīng)把每個字段的特別要求輸送到前端弟头。
和其他不同的是,create的Meta下可以額外增加一個tabs涉茧,結(jié)構(gòu)為:
tabs = [{
'label': '基本信息',
'fields': ['mobile', 'name', 'region', 'desc']
}, {
'label': '權(quán)限配置',
'fields': ['master', 'admins', 'new', 'old', 'rent']
}]
這樣設(shè)定赴恨,前端就可以得到這個tabs,可以用于添加表單分步執(zhí)行降瞳。
輸出到前端后嘱支,對應(yīng)參數(shù)健名為:create
read_class
讀取詳細內(nèi)容的序列化器,要注意的是最好不要構(gòu)建外鍵對象挣饥,而是要用serializers.StringRelatedField()方法把外鍵進行文本化除师,這樣才能在前端正常顯示。
輸出到前端后扔枫,對應(yīng)參數(shù)健名為:read
extra
這個用于額外給前端一個擴展的數(shù)據(jù)字段汛聚,可以設(shè)定一切能夠轉(zhuǎn)為json的數(shù)據(jù),用于自己定義與前端的協(xié)議
輸入到前端后短荐,對應(yīng)參數(shù)健名為:extra