django-virtualqueryset 0.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.
- django_virtualqueryset-0.1.0/LICENSE +22 -0
- django_virtualqueryset-0.1.0/PKG-INFO +80 -0
- django_virtualqueryset-0.1.0/README.md +42 -0
- django_virtualqueryset-0.1.0/pyproject.toml +84 -0
- django_virtualqueryset-0.1.0/setup.cfg +4 -0
- django_virtualqueryset-0.1.0/src/django_virtualqueryset.egg-info/PKG-INFO +80 -0
- django_virtualqueryset-0.1.0/src/django_virtualqueryset.egg-info/SOURCES.txt +20 -0
- django_virtualqueryset-0.1.0/src/django_virtualqueryset.egg-info/dependency_links.txt +1 -0
- django_virtualqueryset-0.1.0/src/django_virtualqueryset.egg-info/requires.txt +8 -0
- django_virtualqueryset-0.1.0/src/django_virtualqueryset.egg-info/top_level.txt +1 -0
- django_virtualqueryset-0.1.0/src/virtualqueryset/__init__.py +39 -0
- django_virtualqueryset-0.1.0/src/virtualqueryset/admin.py +9 -0
- django_virtualqueryset-0.1.0/src/virtualqueryset/apps.py +12 -0
- django_virtualqueryset-0.1.0/src/virtualqueryset/managers.py +167 -0
- django_virtualqueryset-0.1.0/src/virtualqueryset/models.py +75 -0
- django_virtualqueryset-0.1.0/src/virtualqueryset/queryset/__init__.py +16 -0
- django_virtualqueryset-0.1.0/src/virtualqueryset/queryset/api.py +117 -0
- django_virtualqueryset-0.1.0/src/virtualqueryset/queryset/base.py +356 -0
- django_virtualqueryset-0.1.0/src/virtualqueryset/queryset/cached.py +151 -0
- django_virtualqueryset-0.1.0/src/virtualqueryset/queryset/config.py +90 -0
- django_virtualqueryset-0.1.0/src/virtualqueryset/queryset/json_qs.py +129 -0
- django_virtualqueryset-0.1.0/tests/test_base_queryset.py +201 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Hicinformatic
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-virtualqueryset
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Django library for QuerySet-like objects not backed by a database
|
|
5
|
+
Author-email: Hicinformatic <hicinformatic@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/hicinformatic/django-virtualqueryset
|
|
8
|
+
Project-URL: Repository, https://github.com/hicinformatic/django-virtualqueryset
|
|
9
|
+
Project-URL: Documentation, https://github.com/hicinformatic/django-virtualqueryset#readme
|
|
10
|
+
Project-URL: Issues, https://github.com/hicinformatic/django-virtualqueryset/issues
|
|
11
|
+
Keywords: django,queryset,virtual-queryset,virtual-model,in-memory,api-queryset,json-queryset,django-orm,python
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Framework :: Django
|
|
16
|
+
Classifier: Framework :: Django :: 3.2
|
|
17
|
+
Classifier: Framework :: Django :: 4.0
|
|
18
|
+
Classifier: Framework :: Django :: 4.1
|
|
19
|
+
Classifier: Framework :: Django :: 4.2
|
|
20
|
+
Classifier: Framework :: Django :: 5.0
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Requires-Dist: Django>=3.2
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=8.3; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-django>=4.5; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
35
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
36
|
+
Requires-Dist: django-stubs>=5.0.0; extra == "dev"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# django-virtualqueryset
|
|
40
|
+
|
|
41
|
+
Django library for creating QuerySet-like objects that are not backed by a database.
|
|
42
|
+
|
|
43
|
+
This is a minimal Django library ready for migration of existing tools.
|
|
44
|
+
|
|
45
|
+
## Purpose
|
|
46
|
+
|
|
47
|
+
Create virtual QuerySets for:
|
|
48
|
+
- Data from external APIs
|
|
49
|
+
- In-memory computed data
|
|
50
|
+
- Configuration/settings as models
|
|
51
|
+
- Read-only models without database tables
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install django-virtualqueryset
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
INSTALLED_APPS = [
|
|
63
|
+
...
|
|
64
|
+
'virtualqueryset',
|
|
65
|
+
]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Development
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
python dev.py venv
|
|
72
|
+
python dev.py install-dev
|
|
73
|
+
python dev.py migrate
|
|
74
|
+
python dev.py test
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT
|
|
80
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# django-virtualqueryset
|
|
2
|
+
|
|
3
|
+
Django library for creating QuerySet-like objects that are not backed by a database.
|
|
4
|
+
|
|
5
|
+
This is a minimal Django library ready for migration of existing tools.
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
Create virtual QuerySets for:
|
|
10
|
+
- Data from external APIs
|
|
11
|
+
- In-memory computed data
|
|
12
|
+
- Configuration/settings as models
|
|
13
|
+
- Read-only models without database tables
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install django-virtualqueryset
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
INSTALLED_APPS = [
|
|
25
|
+
...
|
|
26
|
+
'virtualqueryset',
|
|
27
|
+
]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Development
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
python dev.py venv
|
|
34
|
+
python dev.py install-dev
|
|
35
|
+
python dev.py migrate
|
|
36
|
+
python dev.py test
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## License
|
|
40
|
+
|
|
41
|
+
MIT
|
|
42
|
+
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "django-virtualqueryset"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Django library for QuerySet-like objects not backed by a database"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [{ name = "Hicinformatic", email = "hicinformatic@gmail.com" }]
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
keywords = [
|
|
14
|
+
"django",
|
|
15
|
+
"queryset",
|
|
16
|
+
"virtual-queryset",
|
|
17
|
+
"virtual-model",
|
|
18
|
+
"in-memory",
|
|
19
|
+
"api-queryset",
|
|
20
|
+
"json-queryset",
|
|
21
|
+
"django-orm",
|
|
22
|
+
"python",
|
|
23
|
+
]
|
|
24
|
+
classifiers = [
|
|
25
|
+
"Development Status :: 4 - Beta",
|
|
26
|
+
"Intended Audience :: Developers",
|
|
27
|
+
"License :: OSI Approved :: MIT License",
|
|
28
|
+
"Framework :: Django",
|
|
29
|
+
"Framework :: Django :: 3.2",
|
|
30
|
+
"Framework :: Django :: 4.0",
|
|
31
|
+
"Framework :: Django :: 4.1",
|
|
32
|
+
"Framework :: Django :: 4.2",
|
|
33
|
+
"Framework :: Django :: 5.0",
|
|
34
|
+
"Programming Language :: Python :: 3",
|
|
35
|
+
"Programming Language :: Python :: 3.10",
|
|
36
|
+
"Programming Language :: Python :: 3.11",
|
|
37
|
+
"Programming Language :: Python :: 3.12",
|
|
38
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
39
|
+
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
|
|
40
|
+
]
|
|
41
|
+
dependencies = [
|
|
42
|
+
"Django>=3.2",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[project.urls]
|
|
46
|
+
Homepage = "https://github.com/hicinformatic/django-virtualqueryset"
|
|
47
|
+
Repository = "https://github.com/hicinformatic/django-virtualqueryset"
|
|
48
|
+
Documentation = "https://github.com/hicinformatic/django-virtualqueryset#readme"
|
|
49
|
+
Issues = "https://github.com/hicinformatic/django-virtualqueryset/issues"
|
|
50
|
+
|
|
51
|
+
[project.optional-dependencies]
|
|
52
|
+
dev = [
|
|
53
|
+
"pytest>=8.3",
|
|
54
|
+
"pytest-django>=4.5",
|
|
55
|
+
"ruff>=0.5",
|
|
56
|
+
"mypy>=1.0",
|
|
57
|
+
"django-stubs>=5.0.0",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[tool.setuptools]
|
|
61
|
+
license-files = ["LICENSE"]
|
|
62
|
+
|
|
63
|
+
[tool.setuptools.packages.find]
|
|
64
|
+
where = ["src"]
|
|
65
|
+
include = ["virtualqueryset*"]
|
|
66
|
+
exclude = ["tests*"]
|
|
67
|
+
|
|
68
|
+
[tool.pytest.ini_options]
|
|
69
|
+
DJANGO_SETTINGS_MODULE = "tests.settings"
|
|
70
|
+
testpaths = ["tests"]
|
|
71
|
+
pythonpath = ["src"]
|
|
72
|
+
|
|
73
|
+
[tool.mypy]
|
|
74
|
+
python_version = "3.10"
|
|
75
|
+
warn_return_any = true
|
|
76
|
+
plugins = ["mypy_django_plugin.main"]
|
|
77
|
+
|
|
78
|
+
[tool.django-stubs]
|
|
79
|
+
django_settings_module = "tests.settings"
|
|
80
|
+
|
|
81
|
+
[tool.ruff]
|
|
82
|
+
line-length = 100
|
|
83
|
+
target-version = "py310"
|
|
84
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-virtualqueryset
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Django library for QuerySet-like objects not backed by a database
|
|
5
|
+
Author-email: Hicinformatic <hicinformatic@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/hicinformatic/django-virtualqueryset
|
|
8
|
+
Project-URL: Repository, https://github.com/hicinformatic/django-virtualqueryset
|
|
9
|
+
Project-URL: Documentation, https://github.com/hicinformatic/django-virtualqueryset#readme
|
|
10
|
+
Project-URL: Issues, https://github.com/hicinformatic/django-virtualqueryset/issues
|
|
11
|
+
Keywords: django,queryset,virtual-queryset,virtual-model,in-memory,api-queryset,json-queryset,django-orm,python
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Framework :: Django
|
|
16
|
+
Classifier: Framework :: Django :: 3.2
|
|
17
|
+
Classifier: Framework :: Django :: 4.0
|
|
18
|
+
Classifier: Framework :: Django :: 4.1
|
|
19
|
+
Classifier: Framework :: Django :: 4.2
|
|
20
|
+
Classifier: Framework :: Django :: 5.0
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Requires-Dist: Django>=3.2
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=8.3; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-django>=4.5; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
35
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
36
|
+
Requires-Dist: django-stubs>=5.0.0; extra == "dev"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# django-virtualqueryset
|
|
40
|
+
|
|
41
|
+
Django library for creating QuerySet-like objects that are not backed by a database.
|
|
42
|
+
|
|
43
|
+
This is a minimal Django library ready for migration of existing tools.
|
|
44
|
+
|
|
45
|
+
## Purpose
|
|
46
|
+
|
|
47
|
+
Create virtual QuerySets for:
|
|
48
|
+
- Data from external APIs
|
|
49
|
+
- In-memory computed data
|
|
50
|
+
- Configuration/settings as models
|
|
51
|
+
- Read-only models without database tables
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install django-virtualqueryset
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
INSTALLED_APPS = [
|
|
63
|
+
...
|
|
64
|
+
'virtualqueryset',
|
|
65
|
+
]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Development
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
python dev.py venv
|
|
72
|
+
python dev.py install-dev
|
|
73
|
+
python dev.py migrate
|
|
74
|
+
python dev.py test
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT
|
|
80
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/django_virtualqueryset.egg-info/PKG-INFO
|
|
5
|
+
src/django_virtualqueryset.egg-info/SOURCES.txt
|
|
6
|
+
src/django_virtualqueryset.egg-info/dependency_links.txt
|
|
7
|
+
src/django_virtualqueryset.egg-info/requires.txt
|
|
8
|
+
src/django_virtualqueryset.egg-info/top_level.txt
|
|
9
|
+
src/virtualqueryset/__init__.py
|
|
10
|
+
src/virtualqueryset/admin.py
|
|
11
|
+
src/virtualqueryset/apps.py
|
|
12
|
+
src/virtualqueryset/managers.py
|
|
13
|
+
src/virtualqueryset/models.py
|
|
14
|
+
src/virtualqueryset/queryset/__init__.py
|
|
15
|
+
src/virtualqueryset/queryset/api.py
|
|
16
|
+
src/virtualqueryset/queryset/base.py
|
|
17
|
+
src/virtualqueryset/queryset/cached.py
|
|
18
|
+
src/virtualqueryset/queryset/config.py
|
|
19
|
+
src/virtualqueryset/queryset/json_qs.py
|
|
20
|
+
tests/test_base_queryset.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
virtualqueryset
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Django VirtualQuerySet - QuerySet-like objects not backed by a database."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.1.0"
|
|
4
|
+
|
|
5
|
+
default_app_config = "virtualqueryset.apps.VirtualQuerySetConfig"
|
|
6
|
+
|
|
7
|
+
# QuerySets can be imported at module level
|
|
8
|
+
from .queryset.base import InMemoryQuerySet
|
|
9
|
+
from .queryset.config import ConfigQuerySet
|
|
10
|
+
from .queryset.api import APIQuerySet
|
|
11
|
+
from .queryset.json_qs import JSONQuerySet
|
|
12
|
+
from .queryset.cached import CachedQuerySet
|
|
13
|
+
|
|
14
|
+
# Managers can be imported at module level
|
|
15
|
+
from .managers import (
|
|
16
|
+
VirtualManager,
|
|
17
|
+
ConfigQuerySetManager,
|
|
18
|
+
APIQuerySetManager,
|
|
19
|
+
JSONQuerySetManager,
|
|
20
|
+
CachedQuerySetManager,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# Models should NOT be imported at module level (Django not ready yet)
|
|
24
|
+
# Import them as: from virtualqueryset.models import VirtualModel
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
# QuerySets
|
|
28
|
+
"InMemoryQuerySet",
|
|
29
|
+
"ConfigQuerySet",
|
|
30
|
+
"APIQuerySet",
|
|
31
|
+
"JSONQuerySet",
|
|
32
|
+
"CachedQuerySet",
|
|
33
|
+
# Managers
|
|
34
|
+
"VirtualManager",
|
|
35
|
+
"ConfigQuerySetManager",
|
|
36
|
+
"APIQuerySetManager",
|
|
37
|
+
"JSONQuerySetManager",
|
|
38
|
+
"CachedQuerySetManager",
|
|
39
|
+
]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Django app configuration."""
|
|
2
|
+
|
|
3
|
+
from django.apps import AppConfig
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class VirtualQuerySetConfig(AppConfig):
|
|
7
|
+
"""Configuration for the virtualqueryset app."""
|
|
8
|
+
|
|
9
|
+
default_auto_field = "django.db.models.BigAutoField"
|
|
10
|
+
name = "virtualqueryset"
|
|
11
|
+
verbose_name = "Virtual QuerySet"
|
|
12
|
+
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""Managers for virtual models."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Callable, List, Optional
|
|
4
|
+
|
|
5
|
+
from django.db import models
|
|
6
|
+
|
|
7
|
+
from .queryset.base import InMemoryQuerySet
|
|
8
|
+
from .queryset.config import ConfigQuerySet
|
|
9
|
+
from .queryset.api import APIQuerySet
|
|
10
|
+
from .queryset.json_qs import JSONQuerySet
|
|
11
|
+
from .queryset.cached import CachedQuerySet
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class VirtualManager(models.Manager):
|
|
15
|
+
"""Base manager for virtual models (no database).
|
|
16
|
+
|
|
17
|
+
Subclass and override get_data() to provide data source.
|
|
18
|
+
|
|
19
|
+
Example:
|
|
20
|
+
class MyVirtualModel(models.Model):
|
|
21
|
+
name = models.CharField(max_length=255)
|
|
22
|
+
|
|
23
|
+
objects = MyCustomManager()
|
|
24
|
+
|
|
25
|
+
class Meta:
|
|
26
|
+
managed = False
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
queryset_class = InMemoryQuerySet
|
|
30
|
+
|
|
31
|
+
def get_queryset(self):
|
|
32
|
+
"""Return queryset with data from get_data()."""
|
|
33
|
+
data = self.get_data()
|
|
34
|
+
return self.queryset_class(model=self.model, data=data)
|
|
35
|
+
|
|
36
|
+
def get_data(self) -> List[Any]:
|
|
37
|
+
"""Override this method to provide data source.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
List of model instances or dictionaries
|
|
41
|
+
"""
|
|
42
|
+
return []
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ConfigQuerySetManager(VirtualManager):
|
|
46
|
+
"""Manager that loads data from Django settings.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
setting_name: Name of Django setting to load
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
queryset_class = ConfigQuerySet
|
|
53
|
+
|
|
54
|
+
def __init__(self, setting_name: str):
|
|
55
|
+
"""Initialize with setting name.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
setting_name: Django setting name (e.g., 'INSTALLED_APPS')
|
|
59
|
+
"""
|
|
60
|
+
super().__init__()
|
|
61
|
+
self.setting_name = setting_name
|
|
62
|
+
|
|
63
|
+
def get_queryset(self):
|
|
64
|
+
"""Return queryset with data from Django setting."""
|
|
65
|
+
return self.queryset_class(
|
|
66
|
+
model=self.model, setting_name=self.setting_name
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class APIQuerySetManager(VirtualManager):
|
|
71
|
+
"""Manager that loads data from external API.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
fetch_func: Callable that fetches data from API
|
|
75
|
+
cache_timeout: Cache duration in seconds
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
queryset_class = APIQuerySet
|
|
79
|
+
|
|
80
|
+
def __init__(self, fetch_func: Callable, cache_timeout: int = 300):
|
|
81
|
+
"""Initialize with API fetch function.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
fetch_func: Callable that returns list of data
|
|
85
|
+
cache_timeout: Cache duration in seconds (default: 5 minutes)
|
|
86
|
+
"""
|
|
87
|
+
super().__init__()
|
|
88
|
+
self.fetch_func = fetch_func
|
|
89
|
+
self.cache_timeout = cache_timeout
|
|
90
|
+
|
|
91
|
+
def get_queryset(self):
|
|
92
|
+
"""Return queryset with data from API."""
|
|
93
|
+
return self.queryset_class(
|
|
94
|
+
model=self.model,
|
|
95
|
+
fetch_func=self.fetch_func,
|
|
96
|
+
cache_timeout=self.cache_timeout,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class JSONQuerySetManager(VirtualManager):
|
|
101
|
+
"""Manager that loads data from JSON source.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
json_source: Path to JSON file or JSON string
|
|
105
|
+
json_path: Optional JSONPath to extract nested data
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
queryset_class = JSONQuerySet
|
|
109
|
+
|
|
110
|
+
def __init__(self, json_source, json_path: Optional[str] = None):
|
|
111
|
+
"""Initialize with JSON source.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
json_source: Path to file, JSON string, or dict
|
|
115
|
+
json_path: Optional path to nested data (e.g., 'results.items')
|
|
116
|
+
"""
|
|
117
|
+
super().__init__()
|
|
118
|
+
self.json_source = json_source
|
|
119
|
+
self.json_path = json_path
|
|
120
|
+
|
|
121
|
+
def get_queryset(self):
|
|
122
|
+
"""Return queryset with data from JSON."""
|
|
123
|
+
return self.queryset_class(
|
|
124
|
+
model=self.model,
|
|
125
|
+
json_source=self.json_source,
|
|
126
|
+
json_path=self.json_path,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class CachedQuerySetManager(VirtualManager):
|
|
131
|
+
"""Manager with caching support.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
fetch_func: Callable that fetches data
|
|
135
|
+
cache_key: Unique cache key
|
|
136
|
+
cache_timeout: Cache duration in seconds
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
queryset_class = CachedQuerySet
|
|
140
|
+
|
|
141
|
+
def __init__(
|
|
142
|
+
self,
|
|
143
|
+
fetch_func: Callable,
|
|
144
|
+
cache_key: Optional[str] = None,
|
|
145
|
+
cache_timeout: int = 3600,
|
|
146
|
+
):
|
|
147
|
+
"""Initialize with caching configuration.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
fetch_func: Callable that returns data
|
|
151
|
+
cache_key: Unique cache key (auto-generated if None)
|
|
152
|
+
cache_timeout: Cache duration in seconds (default: 1 hour)
|
|
153
|
+
"""
|
|
154
|
+
super().__init__()
|
|
155
|
+
self.fetch_func = fetch_func
|
|
156
|
+
self.cache_key = cache_key
|
|
157
|
+
self.cache_timeout = cache_timeout
|
|
158
|
+
|
|
159
|
+
def get_queryset(self):
|
|
160
|
+
"""Return queryset with caching."""
|
|
161
|
+
return self.queryset_class(
|
|
162
|
+
model=self.model,
|
|
163
|
+
fetch_func=self.fetch_func,
|
|
164
|
+
cache_key=self.cache_key,
|
|
165
|
+
cache_timeout=self.cache_timeout,
|
|
166
|
+
)
|
|
167
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Base models for virtual models."""
|
|
2
|
+
|
|
3
|
+
from django.db import models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class VirtualModel(models.Model):
|
|
7
|
+
"""Base class for virtual models (no database table).
|
|
8
|
+
|
|
9
|
+
Virtual models behave like Django models but don't have database tables.
|
|
10
|
+
They use in-memory QuerySets to display data from external sources.
|
|
11
|
+
|
|
12
|
+
Features:
|
|
13
|
+
- No migrations created
|
|
14
|
+
- No database queries
|
|
15
|
+
- Compatible with Django admin
|
|
16
|
+
- Read-only by default
|
|
17
|
+
|
|
18
|
+
Example:
|
|
19
|
+
class ConfigSetting(VirtualModel):
|
|
20
|
+
key = models.CharField(max_length=255)
|
|
21
|
+
value = models.TextField()
|
|
22
|
+
|
|
23
|
+
objects = ConfigQuerySetManager('MY_SETTINGS')
|
|
24
|
+
|
|
25
|
+
def __str__(self):
|
|
26
|
+
return self.key
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
class Meta:
|
|
30
|
+
abstract = True
|
|
31
|
+
managed = False
|
|
32
|
+
|
|
33
|
+
def save(self, *args, **kwargs):
|
|
34
|
+
"""Prevent saving virtual models.
|
|
35
|
+
|
|
36
|
+
Override in subclass if you want to implement custom save logic
|
|
37
|
+
(e.g., saving to API, file, cache).
|
|
38
|
+
"""
|
|
39
|
+
raise NotImplementedError(
|
|
40
|
+
f"{self.__class__.__name__} is a virtual model and cannot be saved to database. "
|
|
41
|
+
"Override save() if you want to implement custom persistence."
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
def delete(self, *args, **kwargs):
|
|
45
|
+
"""Prevent deleting virtual models.
|
|
46
|
+
|
|
47
|
+
Override in subclass if you want to implement custom delete logic.
|
|
48
|
+
"""
|
|
49
|
+
raise NotImplementedError(
|
|
50
|
+
f"{self.__class__.__name__} is a virtual model and cannot be deleted from database. "
|
|
51
|
+
"Override delete() if you want to implement custom deletion."
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ReadOnlyVirtualModel(VirtualModel):
|
|
56
|
+
"""Virtual model that is explicitly read-only.
|
|
57
|
+
|
|
58
|
+
Similar to VirtualModel but with more descriptive error messages.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
class Meta:
|
|
62
|
+
abstract = True
|
|
63
|
+
managed = False
|
|
64
|
+
|
|
65
|
+
def save(self, *args, **kwargs):
|
|
66
|
+
"""Read-only models cannot be saved."""
|
|
67
|
+
raise NotImplementedError(
|
|
68
|
+
f"{self.__class__.__name__} is read-only and cannot be modified."
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def delete(self, *args, **kwargs):
|
|
72
|
+
"""Read-only models cannot be deleted."""
|
|
73
|
+
raise NotImplementedError(
|
|
74
|
+
f"{self.__class__.__name__} is read-only and cannot be deleted."
|
|
75
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""QuerySet implementations for virtual models."""
|
|
2
|
+
|
|
3
|
+
from .base import InMemoryQuerySet
|
|
4
|
+
from .config import ConfigQuerySet
|
|
5
|
+
from .api import APIQuerySet
|
|
6
|
+
from .json_qs import JSONQuerySet
|
|
7
|
+
from .cached import CachedQuerySet
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"InMemoryQuerySet",
|
|
11
|
+
"ConfigQuerySet",
|
|
12
|
+
"APIQuerySet",
|
|
13
|
+
"JSONQuerySet",
|
|
14
|
+
"CachedQuerySet",
|
|
15
|
+
]
|
|
16
|
+
|