easyapi-django 1.1.2__tar.gz → 1.1.4__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.
- {easyapi_django-1.1.2/easyapi_django.egg-info → easyapi_django-1.1.4}/PKG-INFO +1 -1
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/base.py +4 -1
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/filters.py +6 -2
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/helpers.py +61 -3
- {easyapi_django-1.1.2 → easyapi_django-1.1.4/easyapi_django.egg-info}/PKG-INFO +1 -1
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/pyproject.toml +1 -1
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/LICENSE +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/MANIFEST.in +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/README.md +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/__init__.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/auth.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/bearer.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/blocking.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/calc.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/calc_resource.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/client_ip.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/constants.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/core/__init__.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/core/endpoint.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/core/resource.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/dates.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/exception.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/__init__.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/cli.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/config.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/generator.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/inspector/__init__.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/inspector/base.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/inspector/mysql.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/inspector/postgres.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/README.md.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/asgi.py.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/env.example.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/gitignore.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/manage.py.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/module/models.py.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/module/resources.py.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/requirements.txt.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/router/endpoints.py.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/router/urls.py.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/run.sh.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/settings/env.py.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/gen/templates/settings/settings.py.j2 +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/management/__init__.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/management/commands/__init__.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/management/commands/mcp_serve.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/mcp/__init__.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/mcp/protocol.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/mcp/schema.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/mcp/server.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/mcp/testing.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/mcp/tool.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/mcp/tools.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/middleware.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/__init__.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/_common.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/apps.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/clients.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/codes.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/constants.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/devices.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/discovery.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/migrations/0001_initial.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/migrations/__init__.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/models.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/resolver.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/resources/__init__.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/resources/authorize.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/resources/device.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/resources/device_authorization.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/resources/register.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/resources/revoke.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/resources/token.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/routes.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/session.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/settings_helper.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/templates/zeromcp_oauth/consent.html +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/templates/zeromcp_oauth/device.html +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/tokens.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/openapi.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/orm/__init__.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/rate_limit.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/redis_config.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/routes.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/schemas.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/security.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/serializer.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/settings_helper.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/tenant/__init__.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/tenant/db_router.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/tenant/registry.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/tenant/tenant.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/util.py +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi_django.egg-info/SOURCES.txt +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi_django.egg-info/dependency_links.txt +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi_django.egg-info/entry_points.txt +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi_django.egg-info/requires.txt +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi_django.egg-info/top_level.txt +0 -0
- {easyapi_django-1.1.2 → easyapi_django-1.1.4}/setup.cfg +0 -0
|
@@ -29,6 +29,7 @@ from .exception import HTTPException
|
|
|
29
29
|
from .helpers import (
|
|
30
30
|
LOCAL_HOST,
|
|
31
31
|
get_edit_related,
|
|
32
|
+
get_list_related_selects,
|
|
32
33
|
get_related_objects,
|
|
33
34
|
get_tz,
|
|
34
35
|
method_not_allowed,
|
|
@@ -1243,7 +1244,9 @@ class BaseResource(CoreResource):
|
|
|
1243
1244
|
start = 0
|
|
1244
1245
|
|
|
1245
1246
|
if self.list_related_fields:
|
|
1246
|
-
self.queryset = self.queryset.select_related(
|
|
1247
|
+
self.queryset = self.queryset.select_related(
|
|
1248
|
+
*get_list_related_selects(self.list_related_fields)
|
|
1249
|
+
)
|
|
1247
1250
|
|
|
1248
1251
|
prefetch_fields = self.list_prefetch_related.keys() if self.list_prefetch_related else []
|
|
1249
1252
|
if prefetch_fields:
|
|
@@ -446,7 +446,8 @@ class Filter(object):
|
|
|
446
446
|
value = timezone.now() - timedelta(days=int(value))
|
|
447
447
|
except ValueError:
|
|
448
448
|
if len(value) > 10:
|
|
449
|
-
|
|
449
|
+
from django.utils.dateparse import parse_datetime as _parse_dt
|
|
450
|
+
value = _parse_dt(value) or datetime.strptime(value[:10], '%Y-%m-%d')
|
|
450
451
|
else:
|
|
451
452
|
value = datetime.strptime(value, '%Y-%m-%d').date()
|
|
452
453
|
|
|
@@ -592,7 +593,10 @@ class Filter(object):
|
|
|
592
593
|
|
|
593
594
|
# Decide whether to compare against empty values
|
|
594
595
|
elif operator in ['isnull', 'isnotnull'] and coalesce:
|
|
595
|
-
|
|
596
|
+
if operator == 'isnull':
|
|
597
|
+
boolean = value if isinstance(value, bool) else True
|
|
598
|
+
else:
|
|
599
|
+
boolean = not value if isinstance(value, bool) else False
|
|
596
600
|
if _type in ['123', 'date', 'fk']:
|
|
597
601
|
_filter = Q(**{'{}__isnull'.format(field): boolean})
|
|
598
602
|
else:
|
|
@@ -2,6 +2,8 @@ import re
|
|
|
2
2
|
import zoneinfo
|
|
3
3
|
from functools import reduce
|
|
4
4
|
|
|
5
|
+
from django.core.exceptions import ObjectDoesNotExist
|
|
6
|
+
|
|
5
7
|
from .exception import HTTPException
|
|
6
8
|
|
|
7
9
|
|
|
@@ -95,6 +97,59 @@ def get_edit_related(args, field):
|
|
|
95
97
|
return args
|
|
96
98
|
|
|
97
99
|
|
|
100
|
+
def safe_related_getattr(obj, attr):
|
|
101
|
+
if obj is None:
|
|
102
|
+
return None
|
|
103
|
+
try:
|
|
104
|
+
return getattr(obj, attr, None)
|
|
105
|
+
except ObjectDoesNotExist:
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def set_nested_related_field(result, obj, field):
|
|
110
|
+
current_obj = obj
|
|
111
|
+
current_result = result
|
|
112
|
+
parts = field.split('__')
|
|
113
|
+
|
|
114
|
+
for index, part in enumerate(parts):
|
|
115
|
+
value = safe_related_getattr(current_obj, part)
|
|
116
|
+
last = index == len(parts) - 1
|
|
117
|
+
|
|
118
|
+
if last:
|
|
119
|
+
current_result[part] = value
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
if value is None:
|
|
123
|
+
current_result[part] = None
|
|
124
|
+
return
|
|
125
|
+
|
|
126
|
+
existing = current_result.get(part)
|
|
127
|
+
if not isinstance(existing, dict):
|
|
128
|
+
existing = {}
|
|
129
|
+
current_result[part] = existing
|
|
130
|
+
|
|
131
|
+
current_obj = value
|
|
132
|
+
current_result = existing
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def get_list_related_selects(list_related_fields):
|
|
136
|
+
selects = []
|
|
137
|
+
|
|
138
|
+
def add(path):
|
|
139
|
+
if path and path not in selects:
|
|
140
|
+
selects.append(path)
|
|
141
|
+
|
|
142
|
+
for key, fields in list_related_fields.items():
|
|
143
|
+
add(key)
|
|
144
|
+
for field in fields:
|
|
145
|
+
if not isinstance(field, str) or '__' not in field:
|
|
146
|
+
continue
|
|
147
|
+
related_path = '__'.join(field.split('__')[:-1])
|
|
148
|
+
add(f'{key}__{related_path}')
|
|
149
|
+
|
|
150
|
+
return selects
|
|
151
|
+
|
|
152
|
+
|
|
98
153
|
def get_related_objects(args, model):
|
|
99
154
|
obj = args[0]
|
|
100
155
|
result = args[1]
|
|
@@ -102,16 +157,19 @@ def get_related_objects(args, model):
|
|
|
102
157
|
parent = args[3]
|
|
103
158
|
related_models = args[4]
|
|
104
159
|
related_fields = args[5]
|
|
105
|
-
model_obj =
|
|
160
|
+
model_obj = safe_related_getattr(obj, model)
|
|
106
161
|
|
|
107
162
|
if count == 0:
|
|
108
163
|
if model not in related_models:
|
|
109
164
|
related_models[model] = []
|
|
110
165
|
|
|
111
|
-
if model_obj:
|
|
166
|
+
if model_obj is not None:
|
|
112
167
|
result[model] = {}
|
|
113
168
|
for field in related_fields[parent]:
|
|
114
|
-
|
|
169
|
+
if isinstance(field, str) and '__' in field:
|
|
170
|
+
set_nested_related_field(result[model], model_obj, field)
|
|
171
|
+
else:
|
|
172
|
+
result[model][field] = safe_related_getattr(model_obj, field)
|
|
115
173
|
related_models[model].append(field)
|
|
116
174
|
else:
|
|
117
175
|
result[model] = None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/resources/device_authorization.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/templates/zeromcp_oauth/consent.html
RENAMED
|
File without changes
|
{easyapi_django-1.1.2 → easyapi_django-1.1.4}/easyapi/oauth/templates/zeromcp_oauth/device.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|