django-qlab 0.3.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Tabea Hoehne
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.
@@ -0,0 +1,313 @@
1
+ Metadata-Version: 2.4
2
+ Name: django-qlab
3
+ Version: 0.3.0
4
+ Summary: Dynamic query API for Django REST Framework
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Keywords: django,rest,api,query,filter,metadata
8
+ Author: Tabea Hoehne
9
+ Requires-Python: >=3.9
10
+ Classifier: Framework :: Django
11
+ Classifier: Framework :: Django :: 4.0
12
+ Classifier: Framework :: Django :: 4.1
13
+ Classifier: Framework :: Django :: 4.2
14
+ Classifier: Framework :: Django :: 5.0
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: License :: OSI Approved :: MIT License
21
+ Classifier: Intended Audience :: Developers
22
+ Classifier: Topic :: Internet :: WWW/HTTP
23
+ Provides-Extra: dev
24
+ Requires-Dist: Django (>=4.0)
25
+ Requires-Dist: black (>=23.0) ; extra == "dev"
26
+ Requires-Dist: build (>=1.2) ; extra == "dev"
27
+ Requires-Dist: djangorestframework (>=3.14)
28
+ Requires-Dist: drf-spectacular (>=0.26)
29
+ Requires-Dist: pre-commit (>=4.0) ; extra == "dev"
30
+ Requires-Dist: pydantic (>=2.0)
31
+ Requires-Dist: pytest (>=7.0) ; extra == "dev"
32
+ Requires-Dist: pytest-django (>=4.5) ; extra == "dev"
33
+ Requires-Dist: ruff (>=0.1) ; extra == "dev"
34
+ Requires-Dist: twine (>=5.1) ; extra == "dev"
35
+ Project-URL: Documentation, https://github.com/tabeahoehne132/django-qlab#readme
36
+ Project-URL: Homepage, https://github.com/tabeahoehne132/django-qlab
37
+ Project-URL: Repository, https://github.com/tabeahoehne132/django-qlab
38
+ Description-Content-Type: text/markdown
39
+
40
+ # django-qlab
41
+
42
+ Dynamic query API and bundled React UI for Django REST Framework.
43
+ Inspect model data, run filtered queries, save and replay them — no custom views required.
44
+
45
+ [![PyPI version](https://img.shields.io/pypi/v/django-qlab)](https://pypi.org/project/django-qlab/)
46
+ [![Python](https://img.shields.io/pypi/pyversions/django-qlab)](https://pypi.org/project/django-qlab/)
47
+ [![Django](https://img.shields.io/badge/django-4.0%2B-green)](https://pypi.org/project/django-qlab/)
48
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
49
+
50
+ ---
51
+
52
+ ## Screenshots
53
+
54
+ Dashboard:
55
+
56
+ ![QLab dashboard](docs/screenshots/qlab-dashboard.svg)
57
+
58
+ Query builder:
59
+
60
+ ![QLab query builder](docs/screenshots/qlab-query-builder.svg)
61
+
62
+ ---
63
+
64
+ ## What ships
65
+
66
+ - Dynamic model querying with field selection and nested AND / OR / NOT filters
67
+ - Metadata endpoint — fields, types, relations, operators and autocomplete
68
+ - Neighborhood endpoint for relation exploration
69
+ - Bundled React + TypeScript UI served directly from `qlab.urls`
70
+ - Saved queries with create, update, delete and bulk operations
71
+ - Query run history with replay and save-from-history
72
+ - Per-user settings stored in the database
73
+ - Django admin integration for all persistence models
74
+
75
+ ---
76
+
77
+ ## Install
78
+
79
+ ```bash
80
+ pip install django-qlab
81
+ ```
82
+
83
+ Add the required apps:
84
+
85
+ ```python
86
+ # settings.py
87
+ INSTALLED_APPS = [
88
+ ...
89
+ "django.contrib.staticfiles",
90
+ "rest_framework",
91
+ "drf_spectacular",
92
+ "qlab",
93
+ ]
94
+ ```
95
+
96
+ Mount the URLs:
97
+
98
+ ```python
99
+ # urls.py
100
+ from django.urls import include, path
101
+
102
+ urlpatterns = [
103
+ ...
104
+ path("qlab/", include("qlab.urls")),
105
+ ]
106
+ ```
107
+
108
+ Run migrations and collect static files:
109
+
110
+ ```bash
111
+ python manage.py migrate
112
+ python manage.py collectstatic
113
+ ```
114
+
115
+ Open `/qlab/` in your browser — done.
116
+
117
+ ---
118
+
119
+ ## Setup in 5 steps
120
+
121
+ 1. `pip install django-qlab`
122
+ 2. Add `qlab` (and its dependencies) to `INSTALLED_APPS`
123
+ 3. Include `qlab.urls` in your URL config
124
+ 4. `python manage.py migrate && python manage.py collectstatic`
125
+ 5. Open `/qlab/`
126
+
127
+ No separate frontend server. No npm. The compiled UI ships with the package.
128
+
129
+ ---
130
+
131
+ ## Optional: login protection
132
+
133
+ Subclass `QLabView` to enforce authentication on the UI entrypoint:
134
+
135
+ ```python
136
+ # urls.py
137
+ from django.contrib.auth.mixins import LoginRequiredMixin
138
+ from django.urls import include, path
139
+ from qlab.views import QLabView
140
+
141
+ class SecuredQLabView(LoginRequiredMixin, QLabView):
142
+ login_url = "/admin/login/"
143
+
144
+ urlpatterns = [
145
+ path("qlab/", SecuredQLabView.as_view(), name="qlab"),
146
+ path("qlab/", include("qlab.urls")),
147
+ ]
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Optional: queryset scoping
153
+
154
+ Override `QLabFrontendApiViewSet` to scope queries per user, tenant or business group:
155
+
156
+ ```python
157
+ from rest_framework import permissions
158
+ from qlab.api_views import QLabFrontendApiViewSet
159
+
160
+ class ScopedQLabViewSet(QLabFrontendApiViewSet):
161
+ permission_classes = [permissions.IsAuthenticated]
162
+
163
+ def get_queryset(self, model):
164
+ return model.objects.filter(tenant=self.request.user.tenant)
165
+ ```
166
+
167
+ Then mount the scoped ViewSet before the default `qlab.urls` include:
168
+
169
+ ```python
170
+ urlpatterns = [
171
+ path("qlab/", SecuredQLabView.as_view(), name="qlab"),
172
+ path("qlab/api/query/", ScopedQLabViewSet.as_view({"post": "post"}), name="qlab-query"),
173
+ path("qlab/", include("qlab.urls")),
174
+ ]
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Settings
180
+
181
+ Add a `QLAB_SETTINGS` dict to your Django settings to override defaults:
182
+
183
+ ```python
184
+ # settings.py
185
+ QLAB_SETTINGS = {
186
+ "DEFAULT_APP_LABEL": "myapp", # pre-select this app in the UI
187
+ "PAGE_SIZE": 100, # default page size
188
+ "MAX_PAGE_SIZE": 500, # hard cap per request
189
+ "MAX_RELATION_DEPTH": 2, # how deep relation graphs expand
190
+ "MAX_FILTER_CONDITIONS": 10, # max filter nodes per query
191
+ "MAX_NODES": 100, # max records returned by neighborhood
192
+ "ALLOWED_APPS": [], # restrict to specific app labels (empty = all)
193
+ "RESTRICTED_MODELS": [], # block specific model names globally
194
+ }
195
+ ```
196
+
197
+ ---
198
+
199
+ ## API surface
200
+
201
+ All routes are mounted relative to the prefix you chose (e.g. `/qlab/`):
202
+
203
+ | Method | Path | Description |
204
+ |---|---|---|
205
+ | `GET` | `/` | Bundled React UI |
206
+ | `GET` | `/api/bootstrap/` | Initial data load (models, settings) |
207
+ | `POST` | `/api/query/` | Run a filtered, paginated query |
208
+ | `POST` | `/api/metadata/` | Model field and relation schema |
209
+ | `POST` | `/api/neighborhood/` | Relation graph for a set of records |
210
+ | `GET / PATCH` | `/api/settings/` | Per-user UI settings |
211
+ | `GET / POST` | `/api/saved-queries/` | List and create saved queries |
212
+ | `GET / PATCH / DELETE` | `/api/saved-queries/<id>/` | Manage a single saved query |
213
+ | `POST` | `/api/saved-queries/<id>/run/` | Execute a saved query |
214
+ | `GET` | `/api/history/` | Query run history |
215
+
216
+ ### Example query payload
217
+
218
+ ```json
219
+ {
220
+ "model": "Device",
221
+ "app_label": "myapp",
222
+ "select_fields": ["id", "name", "status", "region"],
223
+ "filter_fields": {
224
+ "and_operation": [
225
+ {
226
+ "or_operation": [
227
+ { "field": "status", "op": "is", "value": "active" },
228
+ { "field": "status", "op": "is", "value": "maintenance" }
229
+ ]
230
+ },
231
+ {
232
+ "or_operation": [
233
+ { "field": "region", "op": "is", "value": "DE" },
234
+ { "field": "region", "op": "is", "value": "AT" }
235
+ ]
236
+ }
237
+ ]
238
+ },
239
+ "page": 1,
240
+ "page_size": 100
241
+ }
242
+ ```
243
+
244
+ ---
245
+
246
+ ## UI capabilities
247
+
248
+ - **Dashboard** — model counts, saved query count and recent activity
249
+ - **Query builder** — field picker, nested `(a or b) and (x or y)` filter groups, CSV export, JSON copy
250
+ - **Models browser** — field types, nullability, filterable flags, relation inspection
251
+ - **Saved queries** — create, update, delete, bulk delete and run from the UI
252
+ - **History** — replay past runs, save from history, filter by model and time range
253
+ - **Settings** — page size, default app, theme
254
+ - **Light and dark mode**
255
+
256
+ ---
257
+
258
+ ## Django admin
259
+
260
+ The package registers the following models in Django admin:
261
+
262
+ | Model | Description |
263
+ |---|---|
264
+ | `QLabUserSettings` | Per-user theme, page size and active tab |
265
+ | `SavedQuery` | Stored query payloads with metadata |
266
+ | `QueryRunHistory` | Execution log with status, duration and result snapshot |
267
+
268
+ ---
269
+
270
+ ## Requirements
271
+
272
+ | Package | Version |
273
+ |---|---|
274
+ | Python | ≥ 3.9 |
275
+ | Django | ≥ 4.0 |
276
+ | djangorestframework | ≥ 3.14 |
277
+ | pydantic | ≥ 2.0 |
278
+ | drf-spectacular | ≥ 0.26 |
279
+
280
+ ---
281
+
282
+ ## Frontend development
283
+
284
+ This section is for maintainers working on the UI itself. Package consumers do not need npm.
285
+
286
+ ```bash
287
+ cd frontend
288
+ npm install
289
+ npm run dev # dev server with HMR
290
+ npm run build # write compiled assets to qlab/static/qlab/
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Local demo
296
+
297
+ A gitignored demo project lives in `.local-demo/`:
298
+
299
+ ```bash
300
+ cd .local-demo
301
+ python manage.py migrate
302
+ python manage.py seed_demo_data
303
+ python manage.py runserver 8054
304
+ ```
305
+
306
+ Then open [http://127.0.0.1:8054/qlab/](http://127.0.0.1:8054/qlab/).
307
+
308
+ ---
309
+
310
+ ## License
311
+
312
+ MIT
313
+
@@ -0,0 +1,273 @@
1
+ # django-qlab
2
+
3
+ Dynamic query API and bundled React UI for Django REST Framework.
4
+ Inspect model data, run filtered queries, save and replay them — no custom views required.
5
+
6
+ [![PyPI version](https://img.shields.io/pypi/v/django-qlab)](https://pypi.org/project/django-qlab/)
7
+ [![Python](https://img.shields.io/pypi/pyversions/django-qlab)](https://pypi.org/project/django-qlab/)
8
+ [![Django](https://img.shields.io/badge/django-4.0%2B-green)](https://pypi.org/project/django-qlab/)
9
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
10
+
11
+ ---
12
+
13
+ ## Screenshots
14
+
15
+ Dashboard:
16
+
17
+ ![QLab dashboard](docs/screenshots/qlab-dashboard.svg)
18
+
19
+ Query builder:
20
+
21
+ ![QLab query builder](docs/screenshots/qlab-query-builder.svg)
22
+
23
+ ---
24
+
25
+ ## What ships
26
+
27
+ - Dynamic model querying with field selection and nested AND / OR / NOT filters
28
+ - Metadata endpoint — fields, types, relations, operators and autocomplete
29
+ - Neighborhood endpoint for relation exploration
30
+ - Bundled React + TypeScript UI served directly from `qlab.urls`
31
+ - Saved queries with create, update, delete and bulk operations
32
+ - Query run history with replay and save-from-history
33
+ - Per-user settings stored in the database
34
+ - Django admin integration for all persistence models
35
+
36
+ ---
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ pip install django-qlab
42
+ ```
43
+
44
+ Add the required apps:
45
+
46
+ ```python
47
+ # settings.py
48
+ INSTALLED_APPS = [
49
+ ...
50
+ "django.contrib.staticfiles",
51
+ "rest_framework",
52
+ "drf_spectacular",
53
+ "qlab",
54
+ ]
55
+ ```
56
+
57
+ Mount the URLs:
58
+
59
+ ```python
60
+ # urls.py
61
+ from django.urls import include, path
62
+
63
+ urlpatterns = [
64
+ ...
65
+ path("qlab/", include("qlab.urls")),
66
+ ]
67
+ ```
68
+
69
+ Run migrations and collect static files:
70
+
71
+ ```bash
72
+ python manage.py migrate
73
+ python manage.py collectstatic
74
+ ```
75
+
76
+ Open `/qlab/` in your browser — done.
77
+
78
+ ---
79
+
80
+ ## Setup in 5 steps
81
+
82
+ 1. `pip install django-qlab`
83
+ 2. Add `qlab` (and its dependencies) to `INSTALLED_APPS`
84
+ 3. Include `qlab.urls` in your URL config
85
+ 4. `python manage.py migrate && python manage.py collectstatic`
86
+ 5. Open `/qlab/`
87
+
88
+ No separate frontend server. No npm. The compiled UI ships with the package.
89
+
90
+ ---
91
+
92
+ ## Optional: login protection
93
+
94
+ Subclass `QLabView` to enforce authentication on the UI entrypoint:
95
+
96
+ ```python
97
+ # urls.py
98
+ from django.contrib.auth.mixins import LoginRequiredMixin
99
+ from django.urls import include, path
100
+ from qlab.views import QLabView
101
+
102
+ class SecuredQLabView(LoginRequiredMixin, QLabView):
103
+ login_url = "/admin/login/"
104
+
105
+ urlpatterns = [
106
+ path("qlab/", SecuredQLabView.as_view(), name="qlab"),
107
+ path("qlab/", include("qlab.urls")),
108
+ ]
109
+ ```
110
+
111
+ ---
112
+
113
+ ## Optional: queryset scoping
114
+
115
+ Override `QLabFrontendApiViewSet` to scope queries per user, tenant or business group:
116
+
117
+ ```python
118
+ from rest_framework import permissions
119
+ from qlab.api_views import QLabFrontendApiViewSet
120
+
121
+ class ScopedQLabViewSet(QLabFrontendApiViewSet):
122
+ permission_classes = [permissions.IsAuthenticated]
123
+
124
+ def get_queryset(self, model):
125
+ return model.objects.filter(tenant=self.request.user.tenant)
126
+ ```
127
+
128
+ Then mount the scoped ViewSet before the default `qlab.urls` include:
129
+
130
+ ```python
131
+ urlpatterns = [
132
+ path("qlab/", SecuredQLabView.as_view(), name="qlab"),
133
+ path("qlab/api/query/", ScopedQLabViewSet.as_view({"post": "post"}), name="qlab-query"),
134
+ path("qlab/", include("qlab.urls")),
135
+ ]
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Settings
141
+
142
+ Add a `QLAB_SETTINGS` dict to your Django settings to override defaults:
143
+
144
+ ```python
145
+ # settings.py
146
+ QLAB_SETTINGS = {
147
+ "DEFAULT_APP_LABEL": "myapp", # pre-select this app in the UI
148
+ "PAGE_SIZE": 100, # default page size
149
+ "MAX_PAGE_SIZE": 500, # hard cap per request
150
+ "MAX_RELATION_DEPTH": 2, # how deep relation graphs expand
151
+ "MAX_FILTER_CONDITIONS": 10, # max filter nodes per query
152
+ "MAX_NODES": 100, # max records returned by neighborhood
153
+ "ALLOWED_APPS": [], # restrict to specific app labels (empty = all)
154
+ "RESTRICTED_MODELS": [], # block specific model names globally
155
+ }
156
+ ```
157
+
158
+ ---
159
+
160
+ ## API surface
161
+
162
+ All routes are mounted relative to the prefix you chose (e.g. `/qlab/`):
163
+
164
+ | Method | Path | Description |
165
+ |---|---|---|
166
+ | `GET` | `/` | Bundled React UI |
167
+ | `GET` | `/api/bootstrap/` | Initial data load (models, settings) |
168
+ | `POST` | `/api/query/` | Run a filtered, paginated query |
169
+ | `POST` | `/api/metadata/` | Model field and relation schema |
170
+ | `POST` | `/api/neighborhood/` | Relation graph for a set of records |
171
+ | `GET / PATCH` | `/api/settings/` | Per-user UI settings |
172
+ | `GET / POST` | `/api/saved-queries/` | List and create saved queries |
173
+ | `GET / PATCH / DELETE` | `/api/saved-queries/<id>/` | Manage a single saved query |
174
+ | `POST` | `/api/saved-queries/<id>/run/` | Execute a saved query |
175
+ | `GET` | `/api/history/` | Query run history |
176
+
177
+ ### Example query payload
178
+
179
+ ```json
180
+ {
181
+ "model": "Device",
182
+ "app_label": "myapp",
183
+ "select_fields": ["id", "name", "status", "region"],
184
+ "filter_fields": {
185
+ "and_operation": [
186
+ {
187
+ "or_operation": [
188
+ { "field": "status", "op": "is", "value": "active" },
189
+ { "field": "status", "op": "is", "value": "maintenance" }
190
+ ]
191
+ },
192
+ {
193
+ "or_operation": [
194
+ { "field": "region", "op": "is", "value": "DE" },
195
+ { "field": "region", "op": "is", "value": "AT" }
196
+ ]
197
+ }
198
+ ]
199
+ },
200
+ "page": 1,
201
+ "page_size": 100
202
+ }
203
+ ```
204
+
205
+ ---
206
+
207
+ ## UI capabilities
208
+
209
+ - **Dashboard** — model counts, saved query count and recent activity
210
+ - **Query builder** — field picker, nested `(a or b) and (x or y)` filter groups, CSV export, JSON copy
211
+ - **Models browser** — field types, nullability, filterable flags, relation inspection
212
+ - **Saved queries** — create, update, delete, bulk delete and run from the UI
213
+ - **History** — replay past runs, save from history, filter by model and time range
214
+ - **Settings** — page size, default app, theme
215
+ - **Light and dark mode**
216
+
217
+ ---
218
+
219
+ ## Django admin
220
+
221
+ The package registers the following models in Django admin:
222
+
223
+ | Model | Description |
224
+ |---|---|
225
+ | `QLabUserSettings` | Per-user theme, page size and active tab |
226
+ | `SavedQuery` | Stored query payloads with metadata |
227
+ | `QueryRunHistory` | Execution log with status, duration and result snapshot |
228
+
229
+ ---
230
+
231
+ ## Requirements
232
+
233
+ | Package | Version |
234
+ |---|---|
235
+ | Python | ≥ 3.9 |
236
+ | Django | ≥ 4.0 |
237
+ | djangorestframework | ≥ 3.14 |
238
+ | pydantic | ≥ 2.0 |
239
+ | drf-spectacular | ≥ 0.26 |
240
+
241
+ ---
242
+
243
+ ## Frontend development
244
+
245
+ This section is for maintainers working on the UI itself. Package consumers do not need npm.
246
+
247
+ ```bash
248
+ cd frontend
249
+ npm install
250
+ npm run dev # dev server with HMR
251
+ npm run build # write compiled assets to qlab/static/qlab/
252
+ ```
253
+
254
+ ---
255
+
256
+ ## Local demo
257
+
258
+ A gitignored demo project lives in `.local-demo/`:
259
+
260
+ ```bash
261
+ cd .local-demo
262
+ python manage.py migrate
263
+ python manage.py seed_demo_data
264
+ python manage.py runserver 8054
265
+ ```
266
+
267
+ Then open [http://127.0.0.1:8054/qlab/](http://127.0.0.1:8054/qlab/).
268
+
269
+ ---
270
+
271
+ ## License
272
+
273
+ MIT
@@ -0,0 +1,87 @@
1
+ [build-system]
2
+ requires = ["poetry-core>=1.5.0"]
3
+ build-backend = "poetry.core.masonry.api"
4
+
5
+ [project]
6
+ name = "django-qlab"
7
+ version = "0.3.0"
8
+ description = "Dynamic query API for Django REST Framework"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "Tabea Hoehne"}
14
+ ]
15
+ keywords = ["django", "rest", "api", "query", "filter", "metadata"]
16
+ classifiers = [
17
+ "Framework :: Django",
18
+ "Framework :: Django :: 4.0",
19
+ "Framework :: Django :: 4.1",
20
+ "Framework :: Django :: 4.2",
21
+ "Framework :: Django :: 5.0",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.9",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "License :: OSI Approved :: MIT License",
28
+ "Intended Audience :: Developers",
29
+ "Topic :: Internet :: WWW/HTTP",
30
+ ]
31
+
32
+ dependencies = [
33
+ "Django>=4.0",
34
+ "djangorestframework>=3.14",
35
+ "pydantic>=2.0",
36
+ "drf-spectacular>=0.26",
37
+ ]
38
+
39
+ [project.optional-dependencies]
40
+ dev = [
41
+ "pytest>=7.0",
42
+ "pytest-django>=4.5",
43
+ "black>=23.0",
44
+ "ruff>=0.1",
45
+ "pre-commit>=4.0",
46
+ "build>=1.2",
47
+ "twine>=5.1",
48
+ ]
49
+
50
+ [project.urls]
51
+ Homepage = "https://github.com/tabeahoehne132/django-qlab"
52
+ Documentation = "https://github.com/tabeahoehne132/django-qlab#readme"
53
+ Repository = "https://github.com/tabeahoehne132/django-qlab"
54
+
55
+ [tool.poetry]
56
+ packages = [{include = "qlab"}]
57
+ include = [
58
+ "qlab/templates/**/*",
59
+ "qlab/static/**/*",
60
+ ]
61
+
62
+ [tool.black]
63
+ line-length = 88
64
+ target-version = ["py39"]
65
+ extend-exclude = """
66
+ (
67
+ qlab/static/qlab/.*|
68
+ build/.*|
69
+ django_qlab\\.egg-info/.*|
70
+ frontend/.*|
71
+ docs/.*\\.svg
72
+ )
73
+ """
74
+
75
+ [tool.ruff]
76
+ line-length = 88
77
+ target-version = "py39"
78
+ extend-exclude = [
79
+ "build",
80
+ "django_qlab.egg-info",
81
+ "frontend",
82
+ "qlab/static/qlab",
83
+ ]
84
+
85
+ [tool.ruff.lint]
86
+ select = ["E", "F", "I"]
87
+ ignore = ["E501"]
@@ -0,0 +1,6 @@
1
+ """
2
+ QLab - Dynamic Query API for Django REST Framework
3
+
4
+ Install directly from GitHub:
5
+ pip install git+https://github.com/yourusername/django-qlab.git
6
+ """