accrete 0.0.37__py3-none-any.whl → 0.0.38__py3-none-any.whl
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.
- accrete/contrib/ui/context.py +33 -13
- accrete/contrib/ui/filter.py +1 -1
- accrete/contrib/ui/templatetags/accrete_ui.py +8 -15
- accrete/querystring.py +14 -17
- accrete/utils/models.py +9 -4
- {accrete-0.0.37.dist-info → accrete-0.0.38.dist-info}/METADATA +1 -1
- {accrete-0.0.37.dist-info → accrete-0.0.38.dist-info}/RECORD +9 -9
- {accrete-0.0.37.dist-info → accrete-0.0.38.dist-info}/WHEEL +0 -0
- {accrete-0.0.37.dist-info → accrete-0.0.38.dist-info}/licenses/LICENSE +0 -0
accrete/contrib/ui/context.py
CHANGED
@@ -2,14 +2,18 @@ import logging
|
|
2
2
|
from dataclasses import dataclass, field
|
3
3
|
from typing import TypedDict
|
4
4
|
from django.utils.translation import gettext_lazy as _t
|
5
|
+
from django.db import models
|
5
6
|
from django.db.models import Model, QuerySet
|
6
7
|
from django.core.paginator import Paginator
|
7
8
|
from django.core import paginator
|
8
9
|
from django.forms import Form, ModelForm
|
9
10
|
from accrete.utils.models import get_related_model
|
10
|
-
from .
|
11
|
+
from accrete.annotation import Annotation
|
12
|
+
from .elements import (
|
13
|
+
ClientAction, BreadCrumb, TableField, TableFieldType, TableFieldAlignment
|
14
|
+
)
|
11
15
|
from .filter import Filter
|
12
|
-
|
16
|
+
|
13
17
|
|
14
18
|
_logger = logging.getLogger(__name__)
|
15
19
|
|
@@ -180,34 +184,50 @@ def get_table_fields(
|
|
180
184
|
model: type[Model],
|
181
185
|
field_definition: dict[str | TableField] = None
|
182
186
|
) -> list[TableField]:
|
183
|
-
print(fields, model, field_definition)
|
184
187
|
|
185
|
-
|
186
|
-
|
188
|
+
def get_alignment(field_attr):
|
189
|
+
number_field_types = (
|
190
|
+
models.DecimalField, models.IntegerField, models.FloatField
|
191
|
+
)
|
192
|
+
if (
|
193
|
+
isinstance(field_attr, number_field_types)
|
194
|
+
or (
|
195
|
+
isinstance(field_attr, Annotation)
|
196
|
+
and field_attr.field in number_field_types
|
197
|
+
)):
|
198
|
+
return TableFieldAlignment.RIGHT
|
199
|
+
return TableFieldAlignment.LEFT
|
200
|
+
|
187
201
|
|
188
202
|
def get_field_definition(f_name: str) -> TableField:
|
189
203
|
if definition := field_definition.get(f_name):
|
190
204
|
return definition
|
191
|
-
|
205
|
+
parts = f_name.split('__')
|
206
|
+
if len(parts) == 1:
|
192
207
|
rel_model = model
|
208
|
+
names = [rel_model._meta.verbose_name]
|
193
209
|
else:
|
194
|
-
rel_model = get_related_model(model, f_name)
|
195
|
-
print(rel_model)
|
210
|
+
rel_model, names = get_related_model(model, f_name)
|
196
211
|
try:
|
197
|
-
return rel_model.table_field_definition[
|
212
|
+
return rel_model.table_field_definition[parts[-1]]
|
198
213
|
except (AttributeError, KeyError):
|
199
|
-
attr = getattr(rel_model,
|
214
|
+
attr = getattr(rel_model, parts[-1])
|
200
215
|
if isinstance(attr, Annotation):
|
201
|
-
|
216
|
+
pass
|
202
217
|
elif hasattr(attr, 'field'):
|
203
218
|
attr = attr.field
|
219
|
+
names.append(attr.verbose_name)
|
204
220
|
return TableField(
|
205
|
-
label=str(
|
221
|
+
label=' / '.join([str(name) for name in names[1:]]),
|
206
222
|
name=f_name,
|
207
223
|
header_info=str(attr.help_text),
|
208
|
-
truncate_after=50
|
224
|
+
truncate_after=50,
|
225
|
+
alignment=get_alignment(attr)
|
209
226
|
)
|
210
227
|
|
228
|
+
if field_definition is None:
|
229
|
+
field_definition = {}
|
230
|
+
|
211
231
|
table_fields = []
|
212
232
|
for field_name in fields:
|
213
233
|
try:
|
accrete/contrib/ui/filter.py
CHANGED
@@ -28,27 +28,20 @@ def combine_templates(template_name, request=None):
|
|
28
28
|
|
29
29
|
@register.filter(name='get_attr')
|
30
30
|
def get_attr_from_string(param: object, value: str):
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
attr_name = value.split('__')
|
32
|
+
attr = param
|
33
|
+
for name in attr_name:
|
34
|
+
try:
|
35
|
+
attr = getattr(attr, name)
|
36
|
+
except AttributeError:
|
37
|
+
_logger.exception(f'Object {attr} has no attribute {name}')
|
38
|
+
return ''
|
36
39
|
if callable(attr):
|
37
40
|
return attr()
|
38
41
|
else:
|
39
42
|
return attr
|
40
43
|
|
41
44
|
|
42
|
-
def get_field_value(param: type[Model], value: str):
|
43
|
-
model = param
|
44
|
-
vals = value.split('__')
|
45
|
-
if len(vals) == 1:
|
46
|
-
return get_attr_from_string(model, vals[0])
|
47
|
-
for val in value.split('__'):
|
48
|
-
pass
|
49
|
-
|
50
|
-
|
51
|
-
|
52
45
|
@register.filter(name='message_class')
|
53
46
|
def message_class(param):
|
54
47
|
if param.level == 25:
|
accrete/querystring.py
CHANGED
@@ -2,6 +2,8 @@ import logging
|
|
2
2
|
import json
|
3
3
|
import operator
|
4
4
|
from django.db.models import Model, Q, QuerySet
|
5
|
+
from accrete.utils.models import get_related_model
|
6
|
+
from accrete.annotation import Annotation
|
5
7
|
|
6
8
|
_logger = logging.getLogger(__name__)
|
7
9
|
|
@@ -34,28 +36,23 @@ def parse_querystring(model: type[Model], query_string: str) -> Q:
|
|
34
36
|
expression = Q(**{term: value})
|
35
37
|
return ~expression if invert else expression
|
36
38
|
|
37
|
-
rel_path = parts[
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
rel_path = '__'.join(parts[:-2])
|
40
|
+
related_model, x = get_related_model(model, rel_path)
|
41
|
+
attr = getattr(related_model, parts[-2])
|
42
|
+
if not isinstance(attr, Annotation):
|
43
|
+
expression = Q(**{term: value})
|
44
|
+
return ~expression if invert else expression
|
45
|
+
|
46
|
+
objects = related_model.objects.filter(Q(**{
|
47
|
+
'__'.join(parts[len(x):]): value
|
48
|
+
}))
|
41
49
|
expression = Q(**{
|
42
|
-
f'{rel_path}{"__" if rel_path else ""}id__in':
|
50
|
+
f'{rel_path}{"__" if rel_path else ""}id__in':
|
51
|
+
objects.values_list('id', flat=True)
|
43
52
|
})
|
44
53
|
|
45
54
|
return ~expression if invert else expression
|
46
55
|
|
47
|
-
def get_related_model(rel_path: str):
|
48
|
-
related_model = model
|
49
|
-
for part in rel_path.split('__'):
|
50
|
-
try:
|
51
|
-
related_model = related_model._meta.fields_map[part].related_model
|
52
|
-
except (AttributeError, KeyError):
|
53
|
-
try:
|
54
|
-
related_model = getattr(related_model, part).field.related_model
|
55
|
-
except AttributeError:
|
56
|
-
break
|
57
|
-
return related_model
|
58
|
-
|
59
56
|
def parse_query_block(sub_item) -> Q:
|
60
57
|
op = ops['&']
|
61
58
|
parsed_query = Q()
|
accrete/utils/models.py
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
from django.db.models import Model
|
2
2
|
|
3
3
|
|
4
|
-
def get_related_model(model: type[Model], rel_path: str):
|
4
|
+
def get_related_model(model: type[Model], rel_path: str) -> tuple[Model, list[str]]:
|
5
|
+
names = []
|
5
6
|
related_model = model
|
6
7
|
for part in rel_path.split('__'):
|
8
|
+
names.append(str(related_model._meta.verbose_name))
|
7
9
|
try:
|
8
|
-
|
10
|
+
next_model = related_model._meta.fields_map[part].related_model
|
11
|
+
related_model = next_model
|
9
12
|
except (AttributeError, KeyError):
|
10
13
|
try:
|
11
|
-
|
14
|
+
next_model = getattr(related_model, part).field.related_model
|
15
|
+
if next_model is not None:
|
16
|
+
related_model = next_model
|
12
17
|
except AttributeError:
|
13
18
|
break
|
14
|
-
return related_model
|
19
|
+
return related_model, names
|
@@ -7,7 +7,7 @@ accrete/forms.py,sha256=nPDgSZao-vuVFRam2Py18yiet3Bar-A-qkWjwbeUDlg,11235
|
|
7
7
|
accrete/middleware.py,sha256=RWeHHcYCfpVO4EnG5HMS52F1y5OKRzNCuidMeq6b0zY,3176
|
8
8
|
accrete/models.py,sha256=ruPKqNeKYzqSpYRhpQ12S82iJDYxy0EjSEtNSKWeRz4,6126
|
9
9
|
accrete/queries.py,sha256=bchiqLzE1DmR9kvQ6Yyog6cNlYK_lxpztQMOx6Hy_0c,410
|
10
|
-
accrete/querystring.py,sha256=
|
10
|
+
accrete/querystring.py,sha256=jtPBs3VYQ5_NVwCfjDQV-orv44KHi9b1AAzajvjwYvc,2997
|
11
11
|
accrete/tenant.py,sha256=g3ZuTrQr2zqmIopNBRQeCmHEK2R3dlUme_hOV765J6U,1778
|
12
12
|
accrete/tests.py,sha256=Agltbzwwh5htvq_Qi9vqvxutzmg_GwgPS_N19xJZRlw,7197
|
13
13
|
accrete/views.py,sha256=9-sgCFe_CyG-wllAcIOLujyueiq66C-zg0U7Uf5Y2wU,2954
|
@@ -36,9 +36,9 @@ accrete/contrib/system_mail/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JC
|
|
36
36
|
accrete/contrib/ui/__init__.py,sha256=D_QP3FW_4IzP2c_4WTWyuRIENDA1AFrSOXWL_FNeSMY,445
|
37
37
|
accrete/contrib/ui/admin.py,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63
|
38
38
|
accrete/contrib/ui/apps.py,sha256=E0ao2ox6PQ3ldfeR17FXJUUJuGiWjm2DPCxHbPXGzls,152
|
39
|
-
accrete/contrib/ui/context.py,sha256=
|
39
|
+
accrete/contrib/ui/context.py,sha256=IV66Dtac-MoHelVWrCmFlXQnHZ1XMfwBEYsdZ59-sbg,6870
|
40
40
|
accrete/contrib/ui/elements.py,sha256=g6wksl7hHGJb3CKmkio5rWgcpr1Eyr2vxbKVD-59lkc,1570
|
41
|
-
accrete/contrib/ui/filter.py,sha256=
|
41
|
+
accrete/contrib/ui/filter.py,sha256=0E5dSd58s1mdDhz8WqIX19e0jPBUlEPi5NWFL8PImgA,13050
|
42
42
|
accrete/contrib/ui/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
|
43
43
|
accrete/contrib/ui/urls.py,sha256=TUBlz_CGs9InTZoxM78GSnucA73I8knoh_obt12RUHM,186
|
44
44
|
accrete/contrib/ui/views.py,sha256=WpBKMsxFFG8eG4IN7TW_TPE6i3OFF7gnLDTK7JMKti8,191
|
@@ -151,7 +151,7 @@ accrete/contrib/ui/templates/ui/partials/table_field_float.html,sha256=GH_jFdpk8
|
|
151
151
|
accrete/contrib/ui/templates/ui/partials/table_field_monetary.html,sha256=Wtod9vel2dD4vG8lUVLbtls4aU_2EG3p0E1QRRUSH10,166
|
152
152
|
accrete/contrib/ui/templates/ui/partials/table_field_string.html,sha256=GH_jFdpk8wEJXv4QfO6c3URYrZGGLeuSyWwWl2cWxwQ,45
|
153
153
|
accrete/contrib/ui/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
154
|
-
accrete/contrib/ui/templatetags/accrete_ui.py,sha256=
|
154
|
+
accrete/contrib/ui/templatetags/accrete_ui.py,sha256=NBwRhaqojUGSZal7WI-Ugzl-Qiw6joygarP7B3CsfZc,1462
|
155
155
|
accrete/contrib/user/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
156
156
|
accrete/contrib/user/admin.py,sha256=YS4iApli7XUaIl9GsEJxys2j8sepX0by88omYHjff-E,85
|
157
157
|
accrete/contrib/user/apps.py,sha256=oHDrAiHf-G57mZLyxqGJzRY2DbPprGFD-QgyVJG_ruI,156
|
@@ -189,8 +189,8 @@ accrete/migrations/0002_initial.py,sha256=dFOM7kdHlx7pVAh8cTDlZMtciN4O9Z547HAzEK
|
|
189
189
|
accrete/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
190
190
|
accrete/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
191
191
|
accrete/utils/dates.py,sha256=apM6kt6JhGrKgoT0jfav1W-8AUVTxNc9xt3fJQ2n0JI,1492
|
192
|
-
accrete/utils/models.py,sha256=
|
193
|
-
accrete-0.0.
|
194
|
-
accrete-0.0.
|
195
|
-
accrete-0.0.
|
196
|
-
accrete-0.0.
|
192
|
+
accrete/utils/models.py,sha256=EEhv7-sQVtQD24PEb3XcDUAh3VVhVFoMMLyFrDjGEaI,706
|
193
|
+
accrete-0.0.38.dist-info/METADATA,sha256=qCGJ5Bvnu6mpV3aC_R8hV6bMl2VYNjmeX2T_AhoHFqA,4892
|
194
|
+
accrete-0.0.38.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
|
195
|
+
accrete-0.0.38.dist-info/licenses/LICENSE,sha256=_7laeMIHnsd3Y2vJEXDYXq_PEXxIcjgJsGt8UIKTRWc,1057
|
196
|
+
accrete-0.0.38.dist-info/RECORD,,
|
File without changes
|
File without changes
|