some correct

This commit is contained in:
caoqianming 2020-06-09 16:10:35 +08:00
parent 67df4b297f
commit 66208baf14
16 changed files with 178 additions and 101 deletions

View File

@ -361,7 +361,7 @@ export function genTree(data) {
map[item.id] = item map[item.id] = item
}) })
data.forEach(item => { data.forEach(item => {
const parent = map[item.pid] const parent = map[item.parent]
if (parent) { if (parent) {
(parent.children || (parent.children = [])).push(item) (parent.children || (parent.children = [])).push(item)
} else { } else {

View File

@ -60,8 +60,7 @@ service.interceptors.response.use(
type: 'error', type: 'error',
duration: 5 * 1000 duration: 5 * 1000
}) })
return Promise.reject(new Error(res.msg || '请求出错'))
// return Promise.reject(new Error(res.error || '请求出错'))
} else { } else {
return res return res
} }

View File

@ -63,7 +63,7 @@
<template slot-scope="scope">{{ scope.row.name }}</template> <template slot-scope="scope">{{ scope.row.name }}</template>
</el-table-column> </el-table-column>
<el-table-column align="header-center" label="描述"> <el-table-column align="header-center" label="描述">
<template slot-scope="scope">{{ scope.row.desc }}</template> <template slot-scope="scope">{{ scope.row.description }}</template>
</el-table-column> </el-table-column>
<el-table-column align="header-center" label="排序"> <el-table-column align="header-center" label="排序">
<template <template
@ -111,8 +111,8 @@
<el-form-item label="代号" prop="code"> <el-form-item label="代号" prop="code">
<el-input v-model="dicttype.code" placeholder="代号" /> <el-input v-model="dicttype.code" placeholder="代号" />
</el-form-item> </el-form-item>
<el-form-item label="父级" prop="pid"> <el-form-item label="父级" prop="parent">
<treeselect v-model="dicttype.pid" :multiple="false" :options="dictTypeData" placeholder="父级"/> <treeselect v-model="dicttype.parent" :multiple="false" :options="dictTypeData" placeholder="父级"/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div style="text-align:right;"> <div style="text-align:right;">
@ -125,8 +125,8 @@
<el-form-item label="名称" prop="name"> <el-form-item label="名称" prop="name">
<el-input v-model="dict.name" placeholder="名称" /> <el-input v-model="dict.name" placeholder="名称" />
</el-form-item> </el-form-item>
<el-form-item label="描述" prop="desc"> <el-form-item label="描述" prop="description">
<el-input v-model="dict.desc" placeholder="描述" /> <el-input v-model="dict.description" placeholder="描述" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<div style="text-align:right;"> <div style="text-align:right;">
@ -158,12 +158,12 @@ const defaultDictType = {
id: '', id: '',
name: '', name: '',
code: '', code: '',
pid: null parent: null
} }
const defaultDict = { const defaultDict = {
id: '', id: '',
name: '', name: '',
desc: '', description: '',
sort: 1, sort: 1,
type: null type: null
} }

View File

@ -59,8 +59,8 @@
<el-form-item label="名称" prop="name"> <el-form-item label="名称" prop="name">
<el-input v-model="org.name" placeholder="名称" /> <el-input v-model="org.name" placeholder="名称" />
</el-form-item> </el-form-item>
<el-form-item label="上级部门" prop="pid"> <el-form-item label="上级部门" prop="parent">
<treeselect v-model="org.pid" :multiple="false" :options="tableData" placeholder="父级"/> <treeselect v-model="org.parent" :multiple="false" :options="tableData" placeholder="父级"/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div style="text-align:right;"> <div style="text-align:right;">
@ -81,7 +81,7 @@ import '@riophae/vue-treeselect/dist/vue-treeselect.css'
const defaultOrg = { const defaultOrg = {
id: null, id: null,
name: '', name: '',
pid: null parent: null
} }
export default { export default {
components: { Treeselect }, components: { Treeselect },
@ -90,7 +90,7 @@ export default {
org: { org: {
id: '', id: '',
name: '', name: '',
pid: '' parent: ''
}, },
search: '', search: '',
tableData: [], tableData: [],
@ -100,7 +100,7 @@ export default {
dialogType: 'new', dialogType: 'new',
rule1: { rule1: {
name: [{ required: true, message: '请输入名称', trigger: 'blur' }], name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
pid: [{ required: true, message: '请选择上级', trigger: 'change' }] parent: [{ required: true, message: '请选择上级', trigger: 'change' }]
} }
} }
}, },

View File

@ -69,8 +69,8 @@
<el-form-item label="代号" prop="method"> <el-form-item label="代号" prop="method">
<el-input v-model="perm.method" placeholder="代号" /> <el-input v-model="perm.method" placeholder="代号" />
</el-form-item> </el-form-item>
<el-form-item label="父级" prop="pid"> <el-form-item label="父级" prop="parent">
<treeselect v-model="perm.pid" :multiple="false" :options="tableData" placeholder="父级"/> <treeselect v-model="perm.parent" :multiple="false" :options="tableData" placeholder="父级"/>
</el-form-item> </el-form-item>
<el-form-item label="排序" prop="sort"> <el-form-item label="排序" prop="sort">
<el-input-number v-model="perm.sort" :min="1" label="排序"></el-input-number> <el-input-number v-model="perm.sort" :min="1" label="排序"></el-input-number>
@ -97,7 +97,7 @@ const defaultPerm = {
type: '目录', type: '目录',
method: '', method: '',
sort:1, sort:1,
pid: null parent: null
} }
export default { export default {
components: { Treeselect }, components: { Treeselect },

View File

@ -26,7 +26,7 @@
<template slot-scope="scope">{{ scope.row.name }}</template> <template slot-scope="scope">{{ scope.row.name }}</template>
</el-table-column> </el-table-column>
<el-table-column align="header-center" label="角色描述"> <el-table-column align="header-center" label="角色描述">
<template slot-scope="scope">{{ scope.row.desc }}</template> <template slot-scope="scope">{{ scope.row.description }}</template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="操作"> <el-table-column align="center" label="操作">
<template slot-scope="scope"> <template slot-scope="scope">
@ -43,7 +43,7 @@
</el-form-item> </el-form-item>
<el-form-item label="描述"> <el-form-item label="描述">
<el-input <el-input
v-model="role.desc" v-model="role.description"
:autosize="{ minRows: 2, maxRows: 4}" :autosize="{ minRows: 2, maxRows: 4}"
type="textarea" type="textarea"
placeholder="角色描述" placeholder="角色描述"
@ -112,7 +112,7 @@ import { getOrgAll } from '@/api/org'
const defaultRole = { const defaultRole = {
id: '', id: '',
name: '', name: '',
desc: '', description: '',
perms: [], perms: [],
datas: '本级及以下', datas: '本级及以下',
depts: [] depts: []
@ -252,14 +252,14 @@ export default {
this.getRoleAll() this.getRoleAll()
} }
const { desc, name } = this.role const { description, name } = this.role
this.dialogVisible = false this.dialogVisible = false
this.$notify({ this.$notify({
title: '成功', title: '成功',
dangerouslyUseHTMLString: true, dangerouslyUseHTMLString: true,
message: ` message: `
<div>角色名: ${name}</div> <div>角色名: ${name}</div>
<div>角色描述: ${desc}</div> <div>角色描述: ${description}</div>
`, `,
type: 'success' type: 'success'
}) })

View File

@ -0,0 +1,72 @@
# Generated by Django 3.0.7 on 2020-06-09 07:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('system', '0010_file_path'),
]
operations = [
migrations.AlterModelOptions(
name='file',
options={'verbose_name': '文件库', 'verbose_name_plural': '文件库'},
),
migrations.RenameField(
model_name='dict',
old_name='desc',
new_name='description',
),
migrations.RenameField(
model_name='dict',
old_name='pid',
new_name='parent',
),
migrations.RenameField(
model_name='dicttype',
old_name='pid',
new_name='parent',
),
migrations.RenameField(
model_name='historicaldict',
old_name='desc',
new_name='description',
),
migrations.RenameField(
model_name='historicaldict',
old_name='pid',
new_name='parent',
),
migrations.RenameField(
model_name='organization',
old_name='pid',
new_name='parent',
),
migrations.RenameField(
model_name='permission',
old_name='pid',
new_name='parent',
),
migrations.RenameField(
model_name='position',
old_name='desc',
new_name='description',
),
migrations.RenameField(
model_name='role',
old_name='desc',
new_name='description',
),
migrations.AlterField(
model_name='dict',
name='code',
field=models.CharField(blank=True, max_length=30, null=True, verbose_name='编号'),
),
migrations.AlterField(
model_name='historicaldict',
name='code',
field=models.CharField(blank=True, max_length=30, null=True, verbose_name='编号'),
),
]

View File

@ -21,7 +21,7 @@ class CreateModelBMixin:
业务用基本表B用 业务用基本表B用
""" """
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(create_by = self.request.user, belong_to=self.request.user.dept) serializer.save(create_by = self.request.user, belong_dept=self.request.user.dept)
class UpdateModelBMixin: class UpdateModelBMixin:
""" """

View File

@ -14,7 +14,7 @@ class Position(BaseModel):
职位/岗位 职位/岗位
""" """
name = models.CharField('名称', max_length=32, unique=True) name = models.CharField('名称', max_length=32, unique=True)
desc = models.CharField('描述', max_length=50, blank=True, null=True) description = models.CharField('描述', max_length=50, blank=True, null=True)
class Meta: class Meta:
verbose_name = '职位/岗位' verbose_name = '职位/岗位'
@ -38,7 +38,7 @@ class Permission(SoftModel):
choices=menu_type_choices, default='接口') choices=menu_type_choices, default='接口')
is_frame = models.BooleanField('外部链接', default=False) is_frame = models.BooleanField('外部链接', default=False)
sort = models.IntegerField('排序标记', default=1) sort = models.IntegerField('排序标记', default=1)
pid = models.ForeignKey('self', null=True, blank=True, parent = models.ForeignKey('self', null=True, blank=True,
on_delete=models.SET_NULL, verbose_name='') on_delete=models.SET_NULL, verbose_name='')
method = models.CharField('方法/代号', max_length=50, method = models.CharField('方法/代号', max_length=50,
unique=True, null=True, blank=True) unique=True, null=True, blank=True)
@ -63,7 +63,7 @@ class Organization(SoftModel):
name = models.CharField('名称', max_length=60) name = models.CharField('名称', max_length=60)
type = models.CharField('类型', max_length=20, type = models.CharField('类型', max_length=20,
choices=organization_type_choices, default='部门') choices=organization_type_choices, default='部门')
pid = models.ForeignKey('self', null=True, blank=True, parent = models.ForeignKey('self', null=True, blank=True,
on_delete=models.SET_NULL, verbose_name='') on_delete=models.SET_NULL, verbose_name='')
class Meta: class Meta:
@ -92,7 +92,7 @@ class Role(SoftModel):
choices=data_type_choices, default='本级及以下') choices=data_type_choices, default='本级及以下')
depts = models.ManyToManyField( depts = models.ManyToManyField(
Organization, blank=True, verbose_name='权限范围') Organization, blank=True, verbose_name='权限范围')
desc = models.CharField('描述', max_length=50, blank=True, null=True) description = models.CharField('描述', max_length=50, blank=True, null=True)
class Meta: class Meta:
verbose_name = '角色' verbose_name = '角色'
@ -132,7 +132,7 @@ class DictType(SoftModel):
""" """
name = models.CharField('名称', max_length=30) name = models.CharField('名称', max_length=30)
code = models.CharField('代号', unique=True, max_length=30) code = models.CharField('代号', unique=True, max_length=30)
pid = models.ForeignKey('self', null=True, blank=True, parent = models.ForeignKey('self', null=True, blank=True,
on_delete=models.SET_NULL, verbose_name='') on_delete=models.SET_NULL, verbose_name='')
class Meta: class Meta:
@ -148,13 +148,13 @@ class Dict(SoftModel):
数据字典 数据字典
""" """
name = models.CharField('名称', max_length=30, unique=True) name = models.CharField('名称', max_length=30, unique=True)
code = models.CharField('代码', max_length=30, null=True, blank=True) code = models.CharField('编号', max_length=30, null=True, blank=True)
desc = models.TextField('描述', blank=True, null=True) description = models.TextField('描述', blank=True, null=True)
enabled = models.BooleanField('是否有效', default=True) enabled = models.BooleanField('是否有效', default=True)
type = models.ForeignKey( type = models.ForeignKey(
DictType, on_delete=models.CASCADE, verbose_name='类型') DictType, on_delete=models.CASCADE, verbose_name='类型')
sort = models.IntegerField('排序', default=1) sort = models.IntegerField('排序', default=1)
pid = models.ForeignKey('self', null=True, blank=True, parent = models.ForeignKey('self', null=True, blank=True,
on_delete=models.SET_NULL, verbose_name='') on_delete=models.SET_NULL, verbose_name='')
history = HistoricalRecords() history = HistoricalRecords()
@ -180,14 +180,14 @@ class CommonAModel(SoftModel):
class CommonBModel(SoftModel): class CommonBModel(SoftModel):
""" """
业务用基本表B,包含create_by, update_by, belong_to字段 业务用基本表B,包含create_by, update_by, belong_dept字段
""" """
create_by = models.ForeignKey( create_by = models.ForeignKey(
User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='创建人', related_name='create_by') User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='创建人', related_name='create_by')
update_by = models.ForeignKey( update_by = models.ForeignKey(
User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='最后编辑人', related_name='update_by') User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='最后编辑人', related_name='update_by')
belong_to = models.ForeignKey( belong_dept = models.ForeignKey(
Organization, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='所属部门', related_name='belong_to') Organization, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='所属部门', related_name='belong_dept')
class Meta: class Meta:
abstract = True abstract = True

View File

@ -66,7 +66,7 @@ def has_obj_perm(user, obj):
""" """
数据权限控权 数据权限控权
返回对象的是否可以操作 返回对象的是否可以操作
需要控数据权限的表需有belong_to, create_by, update_by字段(部门, 创建人, 编辑人) 需要控数据权限的表需有belong_dept, create_by, update_by字段(部门, 创建人, 编辑人)
传入user, obj实例 传入user, obj实例
""" """
roles = user.roles roles = user.roles
@ -75,18 +75,18 @@ def has_obj_perm(user, obj):
return True return True
elif '自定义' in data_range: elif '自定义' in data_range:
if roles.depts.exists(): if roles.depts.exists():
if obj.belong_to not in roles.depts: if obj.belong_dept not in roles.depts:
return False return False
elif '同级及以下' in data_range: elif '同级及以下' in data_range:
if user.dept.pid: if user.dept.parent:
belong_tos = get_child_queryset2(user.dept.pid) belong_depts = get_child_queryset2(user.dept.parent)
if obj.belong_to not in belong_tos: if obj.belong_dept not in belong_depts:
return False return False
elif '本级及以下' in data_range: elif '本级及以下' in data_range:
belong_tos = get_child_queryset2(user.dept) belong_depts = get_child_queryset2(user.dept)
if obj.belong_to not in belong_tos: if obj.belong_dept not in belong_depts:
return False return False
elif '本级' in data_range: elif '本级' in data_range:
if obj.belong_to is not user.dept: if obj.belong_dept is not user.dept:
return False return False
return True return True

View File

@ -9,7 +9,7 @@ class RbacFilterSet(GenericAPIView):
""" """
数据权限控权返回的queryset 数据权限控权返回的queryset
在必须的View下继承 在必须的View下继承
需要控数据权限的表需有belong_to, create_by, update_by字段(部门, 创建人, 编辑人) 需要控数据权限的表需有belong_dept, create_by, update_by字段(部门, 创建人, 编辑人)
""" """
def get_queryset(self): def get_queryset(self):
assert self.queryset is not None, ( assert self.queryset is not None, (
@ -22,7 +22,7 @@ class RbacFilterSet(GenericAPIView):
if isinstance(queryset, QuerySet): if isinstance(queryset, QuerySet):
# Ensure queryset is re-evaluated on each request. # Ensure queryset is re-evaluated on each request.
queryset = queryset.all() queryset = queryset.all()
if hasattr(queryset.model, 'belong_to'): if hasattr(queryset.model, 'belong_dept'):
user = self.request.user user = self.request.user
roles = user.roles roles = user.roles
data_range = roles.values_list('datas', flat=True) data_range = roles.values_list('datas', flat=True)
@ -30,19 +30,19 @@ class RbacFilterSet(GenericAPIView):
return queryset return queryset
elif '自定义' in data_range: elif '自定义' in data_range:
if roles.depts.exists(): if roles.depts.exists():
queryset = queryset.filter(belong_to__in = roles.depts) queryset = queryset.filter(belong_dept__in = roles.depts)
return queryset return queryset
elif '同级及以下' in data_range: elif '同级及以下' in data_range:
if user.dept.pid: if user.dept.parent:
belong_tos = get_child_queryset2(user.dept.pid) belong_depts = get_child_queryset2(user.dept.parent)
queryset = queryset.filter(belong_to__in = belong_tos) queryset = queryset.filter(belong_dept__in = belong_depts)
return queryset return queryset
elif '本级及以下' in data_range: elif '本级及以下' in data_range:
belong_tos = get_child_queryset2(user.dept) belong_depts = get_child_queryset2(user.dept)
queryset = queryset.filter(belong_to__in = belong_tos) queryset = queryset.filter(belong_dept__in = belong_depts)
return queryset return queryset
elif '本级' in data_range: elif '本级' in data_range:
queryset = queryset.filter(belong_to = user.dept) queryset = queryset.filter(belong_dept = user.dept)
return queryset return queryset
elif '仅本人' in data_range: elif '仅本人' in data_range:
queryset = queryset.filter(Q(create_by=user)|Q(update_by=user)) queryset = queryset.filter(Q(create_by=user)|Q(update_by=user))
@ -54,29 +54,29 @@ class RbacFilterSet(GenericAPIView):
def rbac_filter_queryset(user, queryset): def rbac_filter_queryset(user, queryset):
""" """
数据权限控权返回的queryset方法 数据权限控权返回的queryset方法
需要控数据权限的表需有belong_to, create_by, update_by字段(部门, 创建人, 编辑人) 需要控数据权限的表需有belong_dept, create_by, update_by字段(部门, 创建人, 编辑人)
传入user实例,queryset 传入user实例,queryset
""" """
roles = user.roles roles = user.roles
data_range = roles.values_list('datas', flat=True) data_range = roles.values_list('datas', flat=True)
if hasattr(queryset.model, 'belong_to'): if hasattr(queryset.model, 'belong_dept'):
if '全部' in data_range: if '全部' in data_range:
return queryset return queryset
elif '自定义' in data_range: elif '自定义' in data_range:
if roles.depts.exists(): if roles.depts.exists():
queryset = queryset.filter(belong_to__in = roles.depts) queryset = queryset.filter(belong_dept__in = roles.depts)
return queryset return queryset
elif '同级及以下' in data_range: elif '同级及以下' in data_range:
if user.dept.pid: if user.dept.parent:
belong_tos = get_child_queryset2(user.dept.pid) belong_depts = get_child_queryset2(user.dept.parent)
queryset = queryset.filter(belong_to__in = belong_tos) queryset = queryset.filter(belong_dept__in = belong_depts)
return queryset return queryset
elif '本级及以下' in data_range: elif '本级及以下' in data_range:
belong_tos = get_child_queryset2(user.dept) belong_depts = get_child_queryset2(user.dept)
queryset = queryset.filter(belong_to__in = belong_tos) queryset = queryset.filter(belong_dept__in = belong_depts)
return queryset return queryset
elif '本级' in data_range: elif '本级' in data_range:
queryset = queryset.filter(belong_to = user.dept) queryset = queryset.filter(belong_dept = user.dept)
return queryset return queryset
elif '仅本人' in data_range: elif '仅本人' in data_range:
queryset = queryset.filter(Q(create_by=user)|Q(update_by=user)) queryset = queryset.filter(Q(create_by=user)|Q(update_by=user))

View File

@ -76,7 +76,7 @@ class DictViewSet(ModelViewSet):
'put': 'dict_update', 'delete': 'dict_delete'} 'put': 'dict_update', 'delete': 'dict_delete'}
queryset = Dict.objects.all() queryset = Dict.objects.all()
serializer_class = DictSerializer serializer_class = DictSerializer
search_fields = ['^name'] search_fields = ['name']
ordering_fields = ['id'] ordering_fields = ['id']
ordering = 'id' ordering = 'id'
@ -90,7 +90,7 @@ class PositionViewSet(ModelViewSet):
queryset = Position.objects.all() queryset = Position.objects.all()
serializer_class = PositionSerializer serializer_class = PositionSerializer
pagination_class = None pagination_class = None
search_fields = ['name','desc'] search_fields = ['name','description']
ordering_fields = ['id'] ordering_fields = ['id']
ordering = 'id' ordering = 'id'
@ -124,7 +124,7 @@ class OrganizationViewSet(ModelViewSet):
queryset = Organization.objects.all() queryset = Organization.objects.all()
serializer_class = OrganizationSerializer serializer_class = OrganizationSerializer
pagination_class = None pagination_class = None
search_fields = ['^name', '^method'] search_fields = ['name', 'method']
ordering_fields = ['id'] ordering_fields = ['id']
ordering = 'id' ordering = 'id'

Binary file not shown.

View File

@ -0,0 +1,6 @@
from rest_framework.pagination import PageNumberPagination
class MyPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'limit'

View File

@ -14,10 +14,10 @@ def get_child_queryset_u(checkQueryset, obj, hasParent=True):
fatherQueryset = cls.objects.filter(pk=obj.id) fatherQueryset = cls.objects.filter(pk=obj.id)
if hasParent: if hasParent:
queryset = queryset | fatherQueryset queryset = queryset | fatherQueryset
child_queryset = checkQueryset.filter(pid=obj) child_queryset = checkQueryset.filter(parent=obj)
while child_queryset: while child_queryset:
queryset = queryset | child_queryset queryset = queryset | child_queryset
child_queryset = checkQueryset.filter(pid__in=child_queryset) child_queryset = checkQueryset.filter(parent__in=child_queryset)
return queryset return queryset
@ -35,10 +35,10 @@ def get_child_queryset(name, pk, hasParent=True):
if fatherQueryset.exists(): if fatherQueryset.exists():
if hasParent: if hasParent:
queryset = queryset | fatherQueryset queryset = queryset | fatherQueryset
child_queryset = cls.objects.filter(pid=fatherQueryset.first()) child_queryset = cls.objects.filter(parent=fatherQueryset.first())
while child_queryset: while child_queryset:
queryset = queryset | child_queryset queryset = queryset | child_queryset
child_queryset = cls.objects.filter(pid__in=child_queryset) child_queryset = cls.objects.filter(parent__in=child_queryset)
return queryset return queryset
def get_child_queryset2(obj, hasParent=True): def get_child_queryset2(obj, hasParent=True):
@ -53,8 +53,8 @@ def get_child_queryset2(obj, hasParent=True):
fatherQueryset = cls.objects.filter(pk=obj.id) fatherQueryset = cls.objects.filter(pk=obj.id)
if hasParent: if hasParent:
queryset = queryset | fatherQueryset queryset = queryset | fatherQueryset
child_queryset = cls.objects.filter(pid=obj) child_queryset = cls.objects.filter(parent=obj)
while child_queryset: while child_queryset:
queryset = queryset | child_queryset queryset = queryset | child_queryset
child_queryset = cls.objects.filter(pid__in=child_queryset) child_queryset = cls.objects.filter(parent__in=child_queryset)
return queryset return queryset

View File

@ -3,37 +3,37 @@ from rest_framework import serializers
class TreeSerializer(serializers.Serializer): # class TreeSerializer(serializers.Serializer):
id = serializers.IntegerField() # id = serializers.IntegerField()
label = serializers.CharField(max_length=20, source='name') # label = serializers.CharField(max_length=20, source='name')
pid = serializers.PrimaryKeyRelatedField(read_only=True) # pid = serializers.PrimaryKeyRelatedField(read_only=True)
class TreeAPIView(ListAPIView): # class TreeAPIView(ListAPIView):
""" # """
自定义树结构View # 自定义树结构View
""" # """
serializer_class = TreeSerializer # serializer_class = TreeSerializer
def list(self, request, *args, **kwargs): # def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset()) # queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset) # page = self.paginate_queryset(queryset)
serializer = self.get_serializer(queryset, many=True) # serializer = self.get_serializer(queryset, many=True)
tree_dict = {} # tree_dict = {}
tree_data = [] # tree_data = []
try: # try:
for item in serializer.data: # for item in serializer.data:
tree_dict[item['id']] = item # tree_dict[item['id']] = item
for i in tree_dict: # for i in tree_dict:
if tree_dict[i]['pid']: # if tree_dict[i]['pid']:
pid = tree_dict[i]['pid'] # pid = tree_dict[i]['pid']
parent = tree_dict[pid] # parent = tree_dict[pid]
parent.setdefault('children', []).append(tree_dict[i]) # parent.setdefault('children', []).append(tree_dict[i])
else: # else:
tree_data.append(tree_dict[i]) # tree_data.append(tree_dict[i])
results = tree_data # results = tree_data
except KeyError: # except KeyError:
results = serializer.data # results = serializer.data
if page is not None: # if page is not None:
return self.get_paginated_response(results) # return self.get_paginated_response(results)
return Response(results) # return Response(results)