utg-base 1.0.1__tar.gz → 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {utg_base-1.0.1 → utg_base-1.1.0}/PKG-INFO +1 -1
- {utg_base-1.0.1 → utg_base-1.1.0}/pyproject.toml +1 -1
- utg_base-1.1.0/src/utg_base/models/__init__.py +2 -0
- utg_base-1.1.0/src/utg_base/models/jwt_user.py +11 -0
- utg_base-1.1.0/src/utg_base/references_api/__init__.py +0 -0
- utg_base-1.1.0/src/utg_base/references_api/admin.py +3 -0
- utg_base-1.1.0/src/utg_base/references_api/apps.py +6 -0
- utg_base-1.1.0/src/utg_base/references_api/migrations/__init__.py +0 -0
- utg_base-1.1.0/src/utg_base/references_api/models.py +3 -0
- utg_base-1.1.0/src/utg_base/references_api/urls.py +13 -0
- utg_base-1.1.0/src/utg_base/references_api/utils.py +181 -0
- {utg_base-1.0.1 → utg_base-1.1.0}/README.md +0 -0
- {utg_base-1.0.1 → utg_base-1.1.0}/src/utg_base/__init__.py +0 -0
- {utg_base-1.0.1 → utg_base-1.1.0}/src/utg_base/api/__init__.py +0 -0
- {utg_base-1.0.1 → utg_base-1.1.0}/src/utg_base/api/pagination.py +0 -0
- {utg_base-1.0.1 → utg_base-1.1.0}/src/utg_base/api/routers.py +0 -0
- {utg_base-1.0.1 → utg_base-1.1.0}/src/utg_base/authentications/__init__.py +0 -0
- {utg_base-1.0.1 → utg_base-1.1.0}/src/utg_base/authentications/microservice_authentication.py +0 -0
- {utg_base-1.0.1 → utg_base-1.1.0}/src/utg_base/authentications/models.py +0 -0
- {utg_base-1.0.1 → utg_base-1.1.0}/src/utg_base/logging.py +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from rest_framework_simplejwt.models import TokenUser
|
|
2
|
+
from rest_framework_simplejwt.tokens import Token
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class JWTUser(TokenUser):
|
|
6
|
+
|
|
7
|
+
def __init__(self, token: "Token"):
|
|
8
|
+
super().__init__(token)
|
|
9
|
+
self.phone = self.token.get("phone")
|
|
10
|
+
self._groups = self.token.get("groups")
|
|
11
|
+
self.should_cache_requests = self.token.get("should_cache_requests")
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from .utils import get_model_classes, create_view_set, get_basename, get_url_prefix
|
|
2
|
+
from ..api.routers import OptionalSlashRouter
|
|
3
|
+
|
|
4
|
+
router = OptionalSlashRouter()
|
|
5
|
+
|
|
6
|
+
for model_class in get_model_classes():
|
|
7
|
+
router.register(
|
|
8
|
+
prefix=get_url_prefix(model_class),
|
|
9
|
+
viewset=create_view_set(model_class),
|
|
10
|
+
basename=get_basename(model_class)
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
urlpatterns = router.urls
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
from urllib.parse import urlparse
|
|
3
|
+
|
|
4
|
+
import inflect
|
|
5
|
+
from django.conf import settings
|
|
6
|
+
from django.db.models import Model, CharField
|
|
7
|
+
from drf_spectacular.utils import extend_schema, extend_schema_serializer
|
|
8
|
+
from rest_framework import filters
|
|
9
|
+
from rest_framework import viewsets, serializers
|
|
10
|
+
|
|
11
|
+
from ..api.views import TranslatedListView
|
|
12
|
+
|
|
13
|
+
serializer_classes = {}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def find_model(model_name: str):
|
|
17
|
+
for model_class in get_model_classes():
|
|
18
|
+
if get_model_class_name(model_class).lower() == model_name.lower():
|
|
19
|
+
return model_class
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_api_meta_property(model: Model, property_name: str):
|
|
23
|
+
if hasattr(model, 'ApiMeta'):
|
|
24
|
+
if hasattr(model.ApiMeta, property_name):
|
|
25
|
+
return getattr(model.ApiMeta, property_name)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_model_class_name(model: Model):
|
|
29
|
+
return model._meta.object_name
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_model_fields_list(model: Model):
|
|
33
|
+
return model._meta.get_fields()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_view_set_name(model: Model):
|
|
37
|
+
return get_model_class_name(model) + 'ViewSet'
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_basename(model: Model):
|
|
41
|
+
return 'admin-' + get_plural_form(get_model_class_name(model).lower())
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def camel_to_snake(name: str):
|
|
45
|
+
return ''.join(map(lambda c: '-' + c.lower() if c.isupper() else c, name)).removeprefix('-')
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def get_url_prefix(model: Model):
|
|
49
|
+
return 'admin/' + get_plural_form(camel_to_snake(get_model_class_name(model))).replace(' ', '-')
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_plural_form(word: str):
|
|
53
|
+
p = inflect.engine()
|
|
54
|
+
return p.plural(word)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_serializer_name(model: Model):
|
|
58
|
+
return get_model_class_name(model) + 'Serializer'
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def get_ordering(model: Model):
|
|
62
|
+
if model._meta.ordering:
|
|
63
|
+
return model._meta.ordering
|
|
64
|
+
if hasattr(model, 'created_at'):
|
|
65
|
+
return ('-created_at',)
|
|
66
|
+
if hasattr(model, 'id'):
|
|
67
|
+
return ('id',)
|
|
68
|
+
return ()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def get_model_classes():
|
|
72
|
+
model_classes = []
|
|
73
|
+
for model_import_path in settings.REFERENCE_API_MODELS:
|
|
74
|
+
module_name, class_name = model_import_path.rsplit('.', 1)
|
|
75
|
+
module = importlib.import_module(module_name)
|
|
76
|
+
model_classes.append(getattr(module, class_name))
|
|
77
|
+
|
|
78
|
+
return model_classes
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def create_view_set(model: Model):
|
|
82
|
+
fields_list = get_model_fields_list(model)
|
|
83
|
+
|
|
84
|
+
@extend_schema(tags=[get_url_prefix(model)])
|
|
85
|
+
class ViewSet(viewsets.ModelViewSet, TranslatedListView):
|
|
86
|
+
http_method_names = get_api_meta_property(model, 'http_method_names') or ['get', 'patch']
|
|
87
|
+
manager = model.objects.order_by(*get_ordering(model))
|
|
88
|
+
filter_backends = [filters.SearchFilter]
|
|
89
|
+
search_fields = (get_api_meta_property(model, 'search_fields') or
|
|
90
|
+
[field.name for field in fields_list if isinstance(field, CharField)])
|
|
91
|
+
|
|
92
|
+
def get_serializer_class(self):
|
|
93
|
+
if self.action == 'create':
|
|
94
|
+
return create_serializer_for_create(model)
|
|
95
|
+
|
|
96
|
+
if self.action == 'partial_update':
|
|
97
|
+
return create_serializer_for_partial_update(model)
|
|
98
|
+
|
|
99
|
+
return create_serializer(model)
|
|
100
|
+
|
|
101
|
+
return ViewSet
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def create_serializer_for_create(model: Model):
|
|
105
|
+
@extend_schema_serializer(component_name='Admin' + get_serializer_name(model))
|
|
106
|
+
class Serializer(serializers.ModelSerializer):
|
|
107
|
+
class Meta:
|
|
108
|
+
fields = '__all__'
|
|
109
|
+
|
|
110
|
+
Serializer.Meta.model = model
|
|
111
|
+
return Serializer
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def create_serializer_for_partial_update(model: Model):
|
|
115
|
+
fields_list = get_model_fields_list(model)
|
|
116
|
+
|
|
117
|
+
@extend_schema_serializer(component_name='Admin' + get_serializer_name(model))
|
|
118
|
+
class Serializer(serializers.ModelSerializer):
|
|
119
|
+
class Meta:
|
|
120
|
+
fields = '__all__'
|
|
121
|
+
read_only_fields = list(
|
|
122
|
+
{
|
|
123
|
+
'created_at',
|
|
124
|
+
'updated_at',
|
|
125
|
+
'deleted_at',
|
|
126
|
+
'created_by',
|
|
127
|
+
'updated_by',
|
|
128
|
+
'deleted_by',
|
|
129
|
+
'code'
|
|
130
|
+
} & set([field.name for field in fields_list])
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
Serializer.Meta.model = model
|
|
134
|
+
return Serializer
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def create_serializer(model: Model, depth=0):
|
|
138
|
+
if get_model_class_name(model) in serializer_classes:
|
|
139
|
+
return serializer_classes[get_model_class_name(model)]
|
|
140
|
+
|
|
141
|
+
fields_list = get_model_fields_list(model)
|
|
142
|
+
|
|
143
|
+
class ImageNameField(serializers.ImageField):
|
|
144
|
+
def to_representation(self, value):
|
|
145
|
+
if not value:
|
|
146
|
+
return None
|
|
147
|
+
parsed_url = urlparse(value.url)
|
|
148
|
+
return f'{parsed_url.path}?{parsed_url.query}'
|
|
149
|
+
|
|
150
|
+
@extend_schema_serializer(component_name='Admin' + get_serializer_name(model))
|
|
151
|
+
class Serializer(serializers.ModelSerializer):
|
|
152
|
+
def __init__(self, *args, **kwargs):
|
|
153
|
+
super().__init__(*args, **kwargs)
|
|
154
|
+
nonlocal model, fields_list
|
|
155
|
+
for field in fields_list:
|
|
156
|
+
if field.__class__.__name__.endswith('ImageField') or field.__class__.__name__.endswith('FileField'):
|
|
157
|
+
self.fields[field.name] = ImageNameField()
|
|
158
|
+
|
|
159
|
+
if field.__class__.__name__.endswith('ForeignKey'):
|
|
160
|
+
model_name = field.name
|
|
161
|
+
_model = find_model(model_name)
|
|
162
|
+
if _model is not None and depth == 0:
|
|
163
|
+
self.fields[model_name] = create_serializer(_model, depth + 1)()
|
|
164
|
+
|
|
165
|
+
class Meta:
|
|
166
|
+
fields = '__all__'
|
|
167
|
+
read_only_fields = list(
|
|
168
|
+
{
|
|
169
|
+
'created_at',
|
|
170
|
+
'updated_at',
|
|
171
|
+
'deleted_at',
|
|
172
|
+
'created_by',
|
|
173
|
+
'updated_by',
|
|
174
|
+
'deleted_by',
|
|
175
|
+
'code'
|
|
176
|
+
} & set([field.name for field in fields_list])
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
Serializer.Meta.model = model
|
|
180
|
+
serializer_classes[get_model_class_name(model)] = Serializer
|
|
181
|
+
return Serializer
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{utg_base-1.0.1 → utg_base-1.1.0}/src/utg_base/authentications/microservice_authentication.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|