-
Notifications
You must be signed in to change notification settings - Fork 0
/
routes.py
138 lines (115 loc) · 3.89 KB
/
routes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""
@Author: WangYuXiang
@E-mile: Hill@3io.cc
@CreateTime: 2021/1/19 16:08
@DependencyLibrary: 无
@MainFunction:无
@FileDoc:
routes.py
便捷路由文件
"""
from collections import namedtuple
# 默认分组
Route = namedtuple('Route', ['url', 'mapping', 'name', 'detail', 'initkwargs', 'is_base'])
class BaseRoute:
def __init__(self, trailing_slash=False):
"""
基础类
:param trailing_slash:
"""
self.trailing_slash = '/' if trailing_slash else ''
self.registry = []
def register(self, viewset: object, prefix: str, basename: str = None, is_base: bool = False):
if basename is None:
basename = prefix.replace('/', '_')
self.registry.append((prefix, viewset, basename, is_base))
# invalidate the urls cache
if hasattr(self, '_urls'):
del self._urls
def get_urls(self):
pass
@property
def urls(self):
if not hasattr(self, '_urls'):
self._urls = self.get_urls()
return self._urls
class ViewSetRouter(BaseRoute):
routes = [
# List route.
Route(
url=r'{prefix}{trailing_slash}',
mapping={
'get': 'list',
'post': 'create'
},
name='{basename}-list',
detail=False,
initkwargs={'suffix': 'List'},
is_base=False,
),
Route(
url=r'{prefix}/<{lookup}:string>{trailing_slash}',
mapping={
'get': 'retrieve',
'put': 'put',
'patch': 'patch',
'delete': 'destroy'
},
name='{basename}-detail',
detail=True,
initkwargs={'suffix': 'Instance'},
is_base=False,
),
]
def get_lookup(self, viewset):
"""
得到主键字段名
:param viewset: 集合视图
:return:
"""
return getattr(viewset, 'lookup_field', 'pk')
def get_urls(self):
"""
Use the registered viewsets to generate a list of URL patterns.
"""
ret = []
for prefix, viewset, basename, is_base in self.registry:
lookup = self.get_lookup(viewset)
for route in self.routes:
# Only actions which actually exist on the viewset will be bound
mapping = self.get_method_map(viewset, route.mapping)
if not mapping:
continue
# Build the url pattern
uri = route.url.format(
prefix=prefix,
lookup=lookup,
trailing_slash=self.trailing_slash
)
# If there is no prefix, the first part of the url is probably
# controlled by project's urls.py and the router is in an app,
# so a slash in the beginning will (A) cause Django to give
# warnings and (B) generate URLS that will require using '//'.
if not prefix and uri[:2] == '^/':
uri = '^' + uri[2:]
initkwargs = route.initkwargs.copy()
initkwargs.update({
'basename': basename,
'detail': route.detail,
})
view = viewset.as_view(mapping, **initkwargs)
name = route.name.format(basename=basename)
ret.append({
'handler': view,
'uri': uri,
'name': name,
'is_base': is_base,
})
return ret
def get_method_map(self, viewset, method_map):
"""得到可用的模型"""
bound_methods = {}
for method, action in method_map.items():
if hasattr(viewset, action):
bound_methods[method] = action
return bound_methods