accrete 0.0.39__py3-none-any.whl → 0.0.40__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/annotation.py CHANGED
@@ -1,4 +1,4 @@
1
- from django.db.models import Field, QuerySet
1
+ from django.db.models import Field
2
2
  from django.db.models.expressions import Func
3
3
  from django.db.models.aggregates import Aggregate
4
4
 
@@ -34,12 +34,10 @@ class AnnotationModelMixin:
34
34
 
35
35
  class AnnotationManagerMixin:
36
36
 
37
- def add_annotations(self, queryset: QuerySet):
38
- model = self.model
39
- if not hasattr(model, 'get_annotations'):
40
- return queryset
41
- return queryset.annotate(**{
37
+ def get_annotations(self):
38
+ if not hasattr(self.model, 'get_annotations'):
39
+ return {}
40
+ return {
42
41
  annotation['name']: annotation['annotation'].function
43
- for annotation in model.get_annotations()
44
- })
45
-
42
+ for annotation in self.model.get_annotations()
43
+ }
@@ -1,15 +1,12 @@
1
- from django.utils import timezone
2
1
  from django.contrib.auth.forms import AuthenticationForm
3
2
  from django.contrib.auth import views, update_session_auth_hash
4
3
  from django.contrib.auth.decorators import login_required
5
- from django.contrib.sessions.models import Session
6
4
  from django.contrib import messages
7
- from django.db.models import Q
8
5
  from django.shortcuts import redirect, render, reverse, resolve_url
9
6
  from django.utils.translation import gettext_lazy as _
10
7
  from django.conf import settings
11
8
 
12
- from accrete.forms import save_form
9
+ from accrete.utils import save_form
13
10
  from accrete.contrib import ui
14
11
  from .forms import UserForm, ChangePasswordForm, ChangeEmailForm
15
12
 
accrete/forms.py CHANGED
@@ -290,22 +290,3 @@ class TenantModelForm(One2ManyModelForm):
290
290
  self.save_o2m()
291
291
 
292
292
  return self.instance
293
-
294
-
295
- def save_form(form, reraise=False):
296
- form.is_saved = False
297
- form.save_error = None
298
- form.save_error_id = None
299
- try:
300
- if form.is_valid():
301
- with transaction.atomic():
302
- form.save()
303
- form.is_saved = True
304
- except Exception as e:
305
- form.save_error = repr(e)
306
- error_id = str(uuid4())[:8]
307
- _logger.exception(f'{error_id}: {e}')
308
- form.save_error_id = error_id
309
- if reraise:
310
- raise e
311
- return form
accrete/managers.py CHANGED
@@ -0,0 +1,35 @@
1
+ from django.db import models
2
+ from accrete.tenant import get_tenant
3
+ from accrete.annotation import AnnotationManagerMixin
4
+
5
+
6
+ class TenantManager(models.Manager, AnnotationManagerMixin):
7
+
8
+ def get_queryset(self):
9
+ queryset = super().get_queryset()
10
+ tenant = get_tenant()
11
+ if tenant:
12
+ queryset = queryset.filter(tenant=tenant)
13
+ return queryset.annotate(**self.get_annotations())
14
+
15
+ def bulk_create(
16
+ self,
17
+ objs,
18
+ batch_size=None,
19
+ ignore_conflicts=False,
20
+ update_conflicts=False,
21
+ update_fields=None,
22
+ unique_fields=None,
23
+ ):
24
+ tenant = get_tenant()
25
+ if tenant is None and not all(obj.tenant_id for obj in objs):
26
+ raise ValueError(
27
+ 'Tenant must be set for all objects when calling bulk_create'
28
+ )
29
+ for obj in objs:
30
+ obj.tenant_id = tenant.pk
31
+ return super().bulk_create(
32
+ objs, batch_size=batch_size, ignore_conflicts=ignore_conflicts,
33
+ update_conflicts=update_conflicts, update_fields=update_fields,
34
+ unique_fields=unique_fields
35
+ )
accrete/models.py CHANGED
@@ -3,39 +3,8 @@ from django.conf import settings
3
3
  from django.utils.translation import gettext_lazy as _
4
4
  from django.contrib.auth.validators import UnicodeUsernameValidator
5
5
  from accrete.tenant import get_tenant
6
- from accrete.annotation import AnnotationModelMixin, AnnotationManagerMixin
7
-
8
-
9
- class TenantManager(models.Manager, AnnotationManagerMixin):
10
-
11
- def get_queryset(self):
12
- queryset = super().get_queryset()
13
- tenant = get_tenant()
14
- if tenant:
15
- queryset = queryset.filter(tenant=tenant)
16
- return self.add_annotations(queryset)
17
-
18
- def bulk_create(
19
- self,
20
- objs,
21
- batch_size=None,
22
- ignore_conflicts=False,
23
- update_conflicts=False,
24
- update_fields=None,
25
- unique_fields=None,
26
- ):
27
- tenant = get_tenant()
28
- if tenant is None and not all(obj.tenant_id for obj in objs):
29
- raise ValueError(
30
- 'Tenant must be set for all objects when calling bulk_create'
31
- )
32
- for obj in objs:
33
- obj.tenant_id = tenant.pk
34
- return super().bulk_create(
35
- objs, batch_size=batch_size, ignore_conflicts=ignore_conflicts,
36
- update_conflicts=update_conflicts, update_fields=update_fields,
37
- unique_fields=unique_fields
38
- )
6
+ from accrete.annotation import AnnotationModelMixin
7
+ from accrete.managers import TenantManager
39
8
 
40
9
 
41
10
  class TenantModel(models.Model, AnnotationModelMixin):
accrete/utils/__init__.py CHANGED
@@ -0,0 +1,4 @@
1
+ from . import dates
2
+ from .forms import save_form
3
+ from .http import filter_from_querystring
4
+ from .models import get_related_model
accrete/utils/forms.py ADDED
@@ -0,0 +1,24 @@
1
+ import logging
2
+ from uuid import uuid4
3
+ from django.db import transaction
4
+
5
+ _logger = logging.getLogger(__name__)
6
+
7
+
8
+ def save_form(form, reraise=False):
9
+ form.is_saved = False
10
+ form.save_error = None
11
+ form.save_error_id = None
12
+ try:
13
+ if form.is_valid():
14
+ with transaction.atomic():
15
+ form.save()
16
+ form.is_saved = True
17
+ except Exception as e:
18
+ form.save_error = repr(e)
19
+ error_id = str(uuid4())[:8]
20
+ _logger.exception(f'{error_id}: {e}')
21
+ form.save_error_id = error_id
22
+ if reraise:
23
+ raise e
24
+ return form
@@ -7,14 +7,24 @@ from accrete.annotation import Annotation
7
7
 
8
8
  _logger = logging.getLogger(__name__)
9
9
 
10
+ Querystring_KEY_MAP = {
11
+ 'querystring': 'q',
12
+ 'order': 'order',
13
+ 'paginate_by': 'paginate_by',
14
+ 'page': 'page'
15
+ }
16
+
10
17
 
11
18
  def filter_from_querystring(
12
- model: type[Model], query_string: str, order: list[str] = None
19
+ model: type[Model], get_params: dict, key_map: dict = None
13
20
  ) -> QuerySet:
14
21
 
15
- order = order or model._meta.ordering
22
+ key_map = key_map or Querystring_KEY_MAP
23
+ querystring = get_params.get(key_map['querystring'], '[]')
24
+ order = get_params.get(key_map['order']) or model._meta.ordering
25
+
16
26
  return model.objects.filter(
17
- parse_querystring(model, query_string)
27
+ parse_querystring(model, querystring)
18
28
  ).order_by(*order).distinct()
19
29
 
20
30
 
@@ -86,4 +96,4 @@ def parse_querystring(model: type[Model], query_string: str) -> Q:
86
96
 
87
97
  ops = {'&': operator.and_, '|': operator.or_, '^': operator.xor}
88
98
  query = parse_query_block(query_data)
89
- return query
99
+ return query
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: accrete
3
- Version: 0.0.39
3
+ Version: 0.0.40
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
@@ -1,14 +1,12 @@
1
1
  accrete/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  accrete/admin.py,sha256=MUYUmCFlGYPowiXTbwl4_Q6Cq0-neiL53WW4P76JCLs,1174
3
- accrete/annotation.py,sha256=MpzKdVDBn2tTLoUTWd9taY3h2dedvQMf3XP7dEtXLrI,1235
3
+ accrete/annotation.py,sha256=P85kNgf_ka3U8i5cwaiKaAiSm21U-xY9PKmXMZR2ulU,1160
4
4
  accrete/apps.py,sha256=F7ynMLHJr_6bRujWtZVUzCliY2CGKiDvyUmL4F68L2E,146
5
5
  accrete/config.py,sha256=eJUbvyBO3DvAD6xkVKjTAzlXy7V7EK9bVyb91girfUs,299
6
- accrete/forms.py,sha256=nPDgSZao-vuVFRam2Py18yiet3Bar-A-qkWjwbeUDlg,11235
7
- accrete/managers.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ accrete/forms.py,sha256=2LobDn8EjHIaqBcgE4_Xk-nbfN6CPQasey-l22cQcT0,10740
7
+ accrete/managers.py,sha256=EvWURMnGadnH3d-wXwv0-sLJKD6uGY03tSCiRSGsKbo,1170
8
8
  accrete/middleware.py,sha256=RWeHHcYCfpVO4EnG5HMS52F1y5OKRzNCuidMeq6b0zY,3176
9
- accrete/models.py,sha256=ruPKqNeKYzqSpYRhpQ12S82iJDYxy0EjSEtNSKWeRz4,6126
10
- accrete/queries.py,sha256=bchiqLzE1DmR9kvQ6Yyog6cNlYK_lxpztQMOx6Hy_0c,410
11
- accrete/querystring.py,sha256=RVKWHIM3Sdvr0ZTG240UOBqDEERq7FwkZpoRts-27v8,2993
9
+ accrete/models.py,sha256=akv8BAT6Q3kxvSujgysg36nxWTizl_D9wAd14DzYhFM,5109
12
10
  accrete/tenant.py,sha256=g3ZuTrQr2zqmIopNBRQeCmHEK2R3dlUme_hOV765J6U,1778
13
11
  accrete/tests.py,sha256=Agltbzwwh5htvq_Qi9vqvxutzmg_GwgPS_N19xJZRlw,7197
14
12
  accrete/views.py,sha256=9-sgCFe_CyG-wllAcIOLujyueiq66C-zg0U7Uf5Y2wU,2954
@@ -161,7 +159,7 @@ accrete/contrib/user/middleware.py,sha256=qblcujwJsthopagyT-hPFq4HsMyGt-VvqZw5TQ
161
159
  accrete/contrib/user/models.py,sha256=SFEXG9G-XY7Nuss7DT51abDv8BWLHKYJocOhQDI_1Lw,3926
162
160
  accrete/contrib/user/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
163
161
  accrete/contrib/user/urls.py,sha256=ktQJ3vZxDlKNUfzOxReeDLOduSdoW5z5Sz0LVFpxZGU,460
164
- accrete/contrib/user/views.py,sha256=82-RPqabxE6o7cglnfZmCUxNNRii4pmVFGiTThE4Zp0,3727
162
+ accrete/contrib/user/views.py,sha256=oNY6HrZpUyCn0NmCRcA93JDwO64dA910F8INkvTo4Hk,3611
165
163
  accrete/contrib/user/locale/de/LC_MESSAGES/django.mo,sha256=p3rgUg6WltAVIMkQsjvjBqTsd_usLhSr1GH4Cyltc2c,433
166
164
  accrete/contrib/user/locale/de/LC_MESSAGES/django.po,sha256=f_Nxpo3HTm2L3f3zoHLfeWsZ-4IQp_EEVSku6TCZSvw,1870
167
165
  accrete/contrib/user/migrations/0001_initial.py,sha256=JWfM9PcMDfkJUdCjLWuWieGs6643qP0KdbCyr5uAZoY,2950
@@ -188,10 +186,12 @@ accrete/contrib/user_registration/templates/user_registration/mail_templates/con
188
186
  accrete/migrations/0001_initial.py,sha256=azThbc8otEhxJwo8BIgOt5eC30mxXhKJLBAazZFe3BA,4166
189
187
  accrete/migrations/0002_initial.py,sha256=dFOM7kdHlx7pVAh8cTDlZMtciN4O9Z547HAzEKnygZE,1628
190
188
  accrete/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
191
- accrete/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
189
+ accrete/utils/__init__.py,sha256=BGXx2NwF4Sc6uaenKNvPZEmHuHVY1u97PPECrd1seA8,129
192
190
  accrete/utils/dates.py,sha256=apM6kt6JhGrKgoT0jfav1W-8AUVTxNc9xt3fJQ2n0JI,1492
191
+ accrete/utils/forms.py,sha256=FHR9IP76dkULCtX4H68xbQG5uvkBQZnDEXSlHyz34iU,606
192
+ accrete/utils/http.py,sha256=dR4p-Q8xoTlrjfx0sN--vkY4ZGtYUsqqquAfPNxsXx8,3249
193
193
  accrete/utils/models.py,sha256=EEhv7-sQVtQD24PEb3XcDUAh3VVhVFoMMLyFrDjGEaI,706
194
- accrete-0.0.39.dist-info/METADATA,sha256=_irD4sQ7BFCpr2vtpIJCNszpZGTSzVIoKMmtKLVpBKE,4892
195
- accrete-0.0.39.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
196
- accrete-0.0.39.dist-info/licenses/LICENSE,sha256=_7laeMIHnsd3Y2vJEXDYXq_PEXxIcjgJsGt8UIKTRWc,1057
197
- accrete-0.0.39.dist-info/RECORD,,
194
+ accrete-0.0.40.dist-info/METADATA,sha256=51Qq-N3iNatoNK4Ot5au42pWHRyxydqijYO5kqk-PUE,4892
195
+ accrete-0.0.40.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
196
+ accrete-0.0.40.dist-info/licenses/LICENSE,sha256=_7laeMIHnsd3Y2vJEXDYXq_PEXxIcjgJsGt8UIKTRWc,1057
197
+ accrete-0.0.40.dist-info/RECORD,,
accrete/queries.py DELETED
@@ -1,18 +0,0 @@
1
- import logging
2
- from accrete import models
3
- from accrete.tenant import get_tenant
4
-
5
- _logger = logging.getLogger(__name__)
6
-
7
-
8
- def is_member(tenant, user):
9
- return tenant.members.filter(user=user, is_active=True).exists()
10
-
11
-
12
- def members_for_current_tenant():
13
- tenant = get_tenant()
14
- return tenant and tenant.members or models.Member.objects.none()
15
-
16
-
17
- def all_tenants():
18
- return models.Tenant.objects.all()