Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Rex Dri
Rex Dri
Commits
b1f1f3e4
Commit
b1f1f3e4
authored
Mar 10, 2019
by
Florent Chehab
Browse files
Further improvements to backend dynamic imports
parent
304fa96f
Pipeline
#36173
passed with stages
in 4 minutes and 51 seconds
Changes
11
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
backend/backend_app/admin.py
View file @
b1f1f3e4
from
django.contrib
import
admin
from
reversion_compare.admin
import
CompareVersionAdmin
from
shared
import
get_api_config
,
get_api_objs
api_config
=
get_api_config
()
from
shared
import
get_api_objs
VERSIONNED_MODELS
=
map
(
lambda
obj
:
obj
.
Model
,
...
...
backend/backend_app/other_viewsets.py
→
backend/backend_app/
models/
other_viewsets.py
View file @
b1f1f3e4
File moved
backend/backend_app/models/user/userData.py
View file @
b1f1f3e4
from
django.contrib.auth.models
import
User
from
django.db
import
models
from
rest_framework
import
serializers
from
backend_app.models.university
import
University
from
backend_app.fields
import
JSONField
from
backend_app.models.abstract.my_model
import
(
MyModel
,
MyModelSerializer
,
MyModelViewSet
,
)
from
django.contrib.auth.models
import
User
from
backend_app.utils
import
get_viewset_permissions
,
get_model_config
,
get_user_level
from
backend_app.models.university
import
University
from
backend_app.permissions.__list_user_post_permission
import
(
list_user_post_permission
,
)
from
backend_app.utils
import
get_model_config
,
get_user_level
,
get_viewset_permissions
from
rest_framework
import
serializers
class
UserData
(
MyModel
):
...
...
backend/backend_app/permissions/__list_user_post_permission.py
View file @
b1f1f3e4
from
django.conf
import
settings
from
dotmap
import
DotMap
from
typing
import
List
from
shared
import
get_api_config
import
importlib
from
django.contrib.auth.models
import
User
api_config
=
get_api_
config
()
from
shared
import
get_api_
objs
ALL_VIEWSETS
=
{}
for
model
in
api_config
:
model
=
DotMap
(
model
)
if
"is_api_view"
in
model
and
model
.
is_api_view
:
continue
if
not
model
.
requires_testing
:
if
model
.
viewset
!=
"UserDataViewSet"
:
module
=
importlib
.
import_module
(
"backend_app.models.{}"
.
format
(
model
.
import_location
)
)
ALL_VIEWSETS
[
model
.
viewset
]
=
getattr
(
module
,
model
.
viewset
)
if
settings
.
TESTING
:
for
model
in
api_config
:
model
=
DotMap
(
model
)
if
"is_api_view"
in
model
and
model
.
is_api_view
:
continue
if
model
.
requires_testing
:
if
model
.
viewset
!=
"UserDataViewSet"
:
module
=
importlib
.
import_module
(
"backend_app.models.{}"
.
format
(
model
.
import_location
)
)
ALL_VIEWSETS
[
model
.
viewset
]
=
getattr
(
module
,
model
.
viewset
)
for
api_obj
in
get_api_objs
(
has_model
=
None
,
requires_testing
=
False
,
is_api_view
=
False
,
ignore_models
=
[
"UserData"
],
):
ALL_VIEWSETS
[
api_obj
.
viewset
]
=
api_obj
.
Viewset
for
api_obj
in
get_api_objs
(
has_model
=
None
,
requires_testing
=
True
,
is_api_view
=
False
,
ignore_models
=
[
"UserData"
]
):
ALL_VIEWSETS
[
api_obj
.
viewset
]
=
api_obj
.
Viewset
class
Request
(
object
):
...
...
@@ -38,7 +26,11 @@ class Request(object):
self
.
method
=
method
def
list_user_post_permission
(
user
):
def
list_user_post_permission
(
user
:
User
)
->
List
[
str
]:
"""
Function the list the viewset to which a user can submit a post request to.
"""
viewsets_user_can_post
=
[]
request
=
Request
(
user
,
"POST"
)
for
viewset_name
in
ALL_VIEWSETS
:
...
...
backend/backend_app/urls.py
View file @
b1f1f3e4
from
django.conf
import
settings
from
django.conf.urls
import
include
,
url
from
rest_framework
import
routers
from
rest_framework.documentation
import
include_docs_urls
from
backend_app.permissions
import
DEFAULT_VIEWSET_PERMISSIONS
from
shared
import
get_api_
config
from
shared
import
get_api_
objs
from
dotmap
import
DotMap
from
.other_viewsets
import
AppModerationStatusViewSet
import
importlib
urlpatterns
=
[
url
(
r
"^api-docs/"
,
include_docs_urls
(
title
=
"Outgoing API"
))]
router
=
routers
.
DefaultRouter
()
ALL_MODELS
=
[]
ALL_VIEWSETS
=
[]
ALL_MODELS
=
map
(
lambda
obj
:
obj
.
Model
,
get_api_objs
(
has_model
=
True
,
ignore_in_admin
=
False
,
requires_testing
=
"smart"
),
)
# Automatically load models and viewset based on API config file
api_config
=
get_api_config
()
ALL_VIEWSETS
=
[]
for
entry
in
api_config
:
model_obj
=
DotMap
(
entry
)
if
"is_api_view"
in
model_obj
and
model_obj
.
is_api_view
:
continue
if
(
not
model_obj
.
requires_testing
)
or
(
settings
.
TESTING
and
model_obj
.
requires_testing
):
module
=
importlib
.
import_module
(
"backend_app.models.{}"
.
format
(
model_obj
.
import_location
)
)
Viewset
=
getattr
(
module
,
model_obj
.
viewset
)
ALL_VIEWSETS
.
append
(
Viewset
)
if
model_obj
.
model
is
not
None
and
not
model_obj
.
ignore_in_admin
:
ALL_MODELS
.
append
(
getattr
(
module
,
model_obj
.
model
))
for
api_obj
in
get_api_objs
(
has_model
=
None
,
requires_testing
=
"smart"
,
is_api_view
=
False
):
ALL_VIEWSETS
.
append
(
api_obj
.
Viewset
)
# Creating the correct router entry
str_url
=
model
_obj
.
api_end_point
if
"api_attr"
in
model
_obj
:
str_url
+=
"/{}"
.
format
(
model
_obj
.
api_attr
)
if
"api_name"
in
model
_obj
:
router
.
register
(
str_url
,
Viewset
,
model
_obj
.
api_name
)
else
:
router
.
register
(
str_url
,
Viewset
)
# Creating the correct router entry
str_url
=
api
_obj
.
api_end_point
if
"api_attr"
in
api
_obj
:
str_url
+=
"/{}"
.
format
(
api
_obj
.
api_attr
)
if
"api_name"
in
api
_obj
:
router
.
register
(
str_url
,
api_obj
.
Viewset
,
api
_obj
.
api_name
)
else
:
router
.
register
(
str_url
,
api_obj
.
Viewset
)
# Add all the endpoints for the base api
urlpatterns
+=
[
url
(
r
"^api/"
,
include
(
router
.
urls
)),
url
(
r
"^api/serverModerationStatus/"
,
AppModerationStatusViewSet
.
as_view
()),
]
urlpatterns
.
append
(
url
(
r
"^api/"
,
include
(
router
.
urls
)))
for
api_obj
in
get_api_objs
(
has_model
=
None
,
requires_testing
=
"smart"
,
is_api_view
=
True
):
urlpatterns
.
append
(
url
(
r
"^api/{}/"
.
format
(
api_obj
.
api_end_point
),
api_obj
.
Viewset
.
as_view
())
)
#######
# Models and Viewset checks
...
...
backend/backend_app/utils/__find_api_end_point_for_viewset.py
View file @
b1f1f3e4
from
shared
import
get
_api_config
from
shared
import
load
_api_config
def
find_api_end_point_for_viewset
(
viewset_name
):
api_config
=
get
_api_config
()
api_config
=
load
_api_config
()
for
obj
in
api_config
:
if
obj
[
"viewset"
]
==
viewset_name
:
return
obj
[
"api_end_point"
]
...
...
backend/backend_app/utils/__get_model_config.py
View file @
b1f1f3e4
from
shared
import
get
_api_config
from
shared
import
load
_api_config
def
get_model_config
(
model
):
api_config
=
get
_api_config
()
api_config
=
load
_api_config
()
for
obj
in
api_config
:
if
"is_api_view"
in
obj
and
obj
[
"is_api_view"
]:
...
...
backend/backend_app/utils/__get_viewset_permissions.py
View file @
b1f1f3e4
...
...
@@ -8,11 +8,11 @@ from backend_app.permissions import (
)
from
rest_framework.permissions
import
IsAdminUser
from
backend_app.permissions
import
DEFAULT_VIEWSET_PERMISSIONS
from
shared
import
get
_api_config
from
shared
import
load
_api_config
def
get_viewset_permissions
(
viewset
):
api_config
=
get
_api_config
()
api_config
=
load
_api_config
()
for
obj
in
api_config
:
if
obj
[
"viewset"
]
==
viewset
:
custom_permission
=
obj
[
"viewset_permission"
]
...
...
shared/__init__.py
View file @
b1f1f3e4
from
.get_api_config
import
get
_api_config
,
get_api_objs
from
.get_api_config
import
load
_api_config
,
get_api_objs
from
.obj_moderation_permission
import
(
DEFAULT_OBJ_MODERATION_LV
,
OBJ_MODERATION_PERMISSIONS
,
)
__all__
=
[
"
get
_api_config"
,
"
load
_api_config"
,
"DEFAULT_OBJ_MODERATION_LV"
,
"OBJ_MODERATION_PERMISSIONS"
,
"get_api_objs"
,
...
...
shared/api_config.yml
View file @
b1f1f3e4
...
...
@@ -38,6 +38,7 @@
-
viewset
:
AppModerationStatusViewSet
api_end_point
:
serverModerationStatus
import_location
:
other_viewsets
read_only
:
true
is_api_view
:
true
...
...
shared/get_api_config.py
View file @
b1f1f3e4
import
importlib
from
os.path
import
dirname
,
join
,
realpath
from
typing
import
List
,
Optional
,
Union
,
Dict
from
django.conf
import
settings
import
yaml
from
os.path
import
join
,
realpath
,
dirname
from
.obj_moderation_permission
import
OBJ_MODERATION_PERMISSIONS
from
dotmap
import
DotMap
from
django.conf
import
settings
import
importlib
from
.obj_moderation_permission
import
OBJ_MODERATION_PERMISSIONS
def
get_api_config
():
def
load_api_config
()
->
List
[
Dict
]:
"""
Returns the list of api objects without filtering add default attributes
added to all objects if they are missing.
"""
current_dir
=
dirname
(
realpath
(
__file__
))
with
open
(
join
(
current_dir
,
"api_config.yml"
),
"r"
)
as
f
:
api_config
=
yaml
.
load
(
f
)
...
...
@@ -35,16 +44,26 @@ def get_api_config():
def
get_api_objs
(
has_model
,
ignore_in_admin
=
None
,
versionned
=
None
,
requires_testing
=
None
,
is_api_view
=
False
,
)
->
dict
:
has_model
:
Optional
[
bool
],
ignore_in_admin
:
Optional
[
bool
]
=
None
,
versionned
:
Optional
[
bool
]
=
None
,
requires_testing
:
Union
[
None
,
bool
,
"smart"
]
=
None
,
is_api_view
:
Optional
[
bool
]
=
False
,
ignore_models
:
List
[
str
]
=
list
(),
)
->
List
[
DotMap
]:
"""
Returns a list of DotMap objects corresponding the api config file
with filtering applied to some attributes.
If the parameter is `None` then no filtering is applied to this attribute.
If the parameter is `True` or `False` the object is returned only if it matched.
There is one exception for the parameter `requires_testing` if it is set to `smart` then
the object is returned only if doesn't require testing or if testing is activated.
"""
out
=
list
()
for
entry
in
get
_api_config
():
for
entry
in
load
_api_config
():
obj
=
DotMap
(
entry
)
if
has_model
is
not
None
:
...
...
@@ -66,12 +85,16 @@ def get_api_objs(
continue
if
requires_testing
is
not
None
:
if
requires_testing
and
not
settings
.
TESTING
:
continue
if
requires_testing
and
not
obj
.
requires_testing
:
continue
if
not
requires_testing
and
obj
.
requires_testing
:
continue
if
requires_testing
==
"smart"
:
if
obj
.
requires_testing
and
not
settings
.
TESTING
:
continue
else
:
if
requires_testing
and
not
settings
.
TESTING
:
continue
if
requires_testing
and
not
obj
.
requires_testing
:
continue
if
not
requires_testing
and
obj
.
requires_testing
:
continue
if
is_api_view
is
not
None
:
if
is_api_view
and
not
obj
.
is_api_view
:
...
...
@@ -84,6 +107,8 @@ def get_api_objs(
)
if
obj
.
model
is
not
None
:
if
obj
.
model
in
ignore_models
:
continue
Model
=
getattr
(
module
,
obj
.
model
)
obj
.
Model
=
Model
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment