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.
@@ -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 .elements import ClientAction, BreadCrumb, TableField, TableFieldType
11
+ from accrete.annotation import Annotation
12
+ from .elements import (
13
+ ClientAction, BreadCrumb, TableField, TableFieldType, TableFieldAlignment
14
+ )
11
15
  from .filter import Filter
12
- from ...annotation import Annotation
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
- if field_definition is None:
186
- field_definition = {}
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
- if len(f_name.split('__')) == 1:
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[f_name]
212
+ return rel_model.table_field_definition[parts[-1]]
198
213
  except (AttributeError, KeyError):
199
- attr = getattr(rel_model, f_name)
214
+ attr = getattr(rel_model, parts[-1])
200
215
  if isinstance(attr, Annotation):
201
- attr = attr
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(attr.verbose_name),
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:
@@ -69,7 +69,7 @@ class Filter:
69
69
  except AttributeError:
70
70
  label = field.related_model._meta.verbose_name
71
71
  res.append({
72
- 'name': field.name,
72
+ 'name': f'{rel_path}',
73
73
  'label': str(label),
74
74
  'type': field.get_internal_type(),
75
75
  'null': field.null,
@@ -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
- try:
32
- attr = getattr(param, value)
33
- except AttributeError:
34
- _logger.exception(f'Object {param} has no attribute {value}')
35
- return ''
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[0].rstrip('__')
38
- term = parts[1]
39
- rel_model = get_related_model(rel_path) if rel_path else model
40
- objects = rel_model.objects.filter(Q(**{term: value}))
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': objects.values_list('id', flat=True)
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
- related_model = related_model._meta.fields_map[part].related_model
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
- related_model = getattr(related_model, part).field.related_model
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: accrete
3
- Version: 0.0.37
3
+ Version: 0.0.38
4
4
  Summary: Django Shared Schema Multi Tenant
5
5
  Author-email: Benedikt Jilek <benedikt.jilek@pm.me>
6
6
  License: Copyright (c) 2023 Benedikt Jilek
@@ -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=TEJ-PhNj1xfA5a2gL6QwD3r33CIcUpLjr5ju0RIgd_I,3140
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=lBX3Ga-54cRDnbmFT28afCypbtwg65qNtjKbiQz2jmI,6242
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=39Kms9jS-ruuursyUbnazrM3DrBsMSEr81Lh6EelUqs,13047
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=ttu2dN5xVMOaON1gyd6Dk22TGt3RQQr97YECrwVgDmw,1593
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=qAdWovkztpvFZHY7VzK4hGIMUjBcA9iQtqYFgz7z2ro,474
193
- accrete-0.0.37.dist-info/METADATA,sha256=DKhGve3m6OHxG8gFRrsGmdShLC6Ttph3HlvB6_5ACQU,4892
194
- accrete-0.0.37.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
195
- accrete-0.0.37.dist-info/licenses/LICENSE,sha256=_7laeMIHnsd3Y2vJEXDYXq_PEXxIcjgJsGt8UIKTRWc,1057
196
- accrete-0.0.37.dist-info/RECORD,,
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,,