djresttoolkit 0.6.2__py3-none-any.whl → 0.8.0__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.
- README.md +133 -8
- {djresttoolkit-0.6.2.dist-info → djresttoolkit-0.8.0.dist-info}/METADATA +136 -9
- {djresttoolkit-0.6.2.dist-info → djresttoolkit-0.8.0.dist-info}/RECORD +11 -7
- src/djresttoolkit/dbseed/models/__init__.py +7 -1
- src/djresttoolkit/dbseed/models/_choice_field.py +17 -0
- src/djresttoolkit/envconfig/__init__.py +3 -0
- src/djresttoolkit/envconfig/_env_settings.py +84 -0
- src/djresttoolkit/management/commands/dbflush.py +94 -0
- {djresttoolkit-0.6.2.dist-info → djresttoolkit-0.8.0.dist-info}/WHEEL +0 -0
- {djresttoolkit-0.6.2.dist-info → djresttoolkit-0.8.0.dist-info}/entry_points.txt +0 -0
- {djresttoolkit-0.6.2.dist-info → djresttoolkit-0.8.0.dist-info}/licenses/LICENSE +0 -0
README.md
CHANGED
@@ -85,7 +85,132 @@ python manage.py dbseed --count 10
|
|
85
85
|
python manage.py dbseed --model User --seed 42
|
86
86
|
```
|
87
87
|
|
88
|
-
|
88
|
+
Here’s a **concise API reference** for your database flush management command for `djresttoolkit`:
|
89
|
+
|
90
|
+
---
|
91
|
+
|
92
|
+
### 2. DB Flush Command
|
93
|
+
|
94
|
+
```python
|
95
|
+
from djresttoolkit.management.commands import flush
|
96
|
+
```
|
97
|
+
|
98
|
+
#### `manage.py dbflush`
|
99
|
+
|
100
|
+
Command to **delete all records** from the database for all models or a specific model and **reset auto-increment IDs**.
|
101
|
+
|
102
|
+
#### Usage
|
103
|
+
|
104
|
+
```bash
|
105
|
+
python manage.py flush [--model ModelName] [--yes]
|
106
|
+
```
|
107
|
+
|
108
|
+
#### dbflush command options
|
109
|
+
|
110
|
+
- `--model`: Name of the model to flush (case-sensitive, e.g., `User`). If omitted, flushes all models.
|
111
|
+
- `--yes`: Skip confirmation prompt. Without this, the command asks for confirmation before deleting.
|
112
|
+
|
113
|
+
#### dbflush command behavior
|
114
|
+
|
115
|
+
- Deletes all records for the specified model or all models.
|
116
|
+
- Resets primary key sequences for supported databases:
|
117
|
+
|
118
|
+
- PostgreSQL: `ALTER SEQUENCE ... RESTART WITH 1`
|
119
|
+
- SQLite: Deletes from `sqlite_sequence` table
|
120
|
+
- Others: Logs a warning (not implemented).
|
121
|
+
- Uses transactions to ensure safe operations.
|
122
|
+
|
123
|
+
#### dbflush command example
|
124
|
+
|
125
|
+
```bash
|
126
|
+
# Flush all models with confirmation
|
127
|
+
python manage.py dbflush
|
128
|
+
|
129
|
+
# Flush a specific model (User) with confirmation
|
130
|
+
python manage.py dbflush --model User
|
131
|
+
|
132
|
+
# Flush all models without prompt
|
133
|
+
python manage.py dbflush --yes
|
134
|
+
```
|
135
|
+
|
136
|
+
#### Output
|
137
|
+
|
138
|
+
```bash
|
139
|
+
Flushed 10 records from model "User" and reset IDs.
|
140
|
+
```
|
141
|
+
|
142
|
+
or
|
143
|
+
|
144
|
+
```bash
|
145
|
+
Flushed 120 records from all models and reset IDs.
|
146
|
+
```
|
147
|
+
|
148
|
+
### 3. EnvBaseSettings
|
149
|
+
|
150
|
+
```python
|
151
|
+
from djresttoolkit.envconfig import EnvBaseSettings
|
152
|
+
```
|
153
|
+
|
154
|
+
#### `EnvBaseSettings`
|
155
|
+
|
156
|
+
A **base settings class** for managing application configuration using:
|
157
|
+
|
158
|
+
- YAML files (default `.environ.yaml`)
|
159
|
+
- Environment variables (default `.env`)
|
160
|
+
|
161
|
+
Supports **nested configuration** using double underscores (`__`) in environment variable names.
|
162
|
+
|
163
|
+
#### Class Attributes
|
164
|
+
|
165
|
+
| Attribute | Type | Default | Description |
|
166
|
+
| -------------- | -------------------- | --------------- | ------------------------------------------------------------------ |
|
167
|
+
| `env_file` | `str` | `.env` | Environment variable file path. |
|
168
|
+
| `yaml_file` | `str` | `.environ.yaml` | YAML configuration file path. |
|
169
|
+
| `model_config` | `SettingsConfigDict` | — | Pydantic settings configuration (file encoding, nested delimiter). |
|
170
|
+
|
171
|
+
#### Methods
|
172
|
+
|
173
|
+
#### `load(cls, *, env_file: str | None = None, ymal_file: str | None = None, warning: bool = True) -> EnvBaseSettings`
|
174
|
+
|
175
|
+
Loads configuration from **YAML first**, then overrides with **environment variables**.
|
176
|
+
|
177
|
+
#### Parameters
|
178
|
+
|
179
|
+
- `env_file` — Optional custom `.env` file path.
|
180
|
+
- `ymal_file` — Optional custom YAML file path.
|
181
|
+
- `warning` — Emit a warning if YAML file is missing (default `True`).
|
182
|
+
|
183
|
+
#### Returns
|
184
|
+
|
185
|
+
- Instance of `EnvBaseSettings` (or subclass) with loaded configuration.
|
186
|
+
|
187
|
+
#### Raises
|
188
|
+
|
189
|
+
- `UserWarning` if YAML file not found and `warning=True`.
|
190
|
+
|
191
|
+
### Usage Example
|
192
|
+
|
193
|
+
```python
|
194
|
+
from djresttoolkit.envconfig import EnvBaseSettings
|
195
|
+
|
196
|
+
class EnvSettings(EnvBaseSettings):
|
197
|
+
debug: bool = False
|
198
|
+
database_url: str
|
199
|
+
|
200
|
+
# Load settings
|
201
|
+
settings = EnvSettings.load(warning=False)
|
202
|
+
|
203
|
+
print(settings.debug)
|
204
|
+
print(settings.database_url)
|
205
|
+
```
|
206
|
+
|
207
|
+
#### Features
|
208
|
+
|
209
|
+
- Prioritizes `.env` variables over YAML.
|
210
|
+
- Supports nested keys: `DATABASE__HOST` → `settings.database.host`.
|
211
|
+
- Designed to be subclassed for project-specific settings.
|
212
|
+
|
213
|
+
### 4. EmailSender
|
89
214
|
|
90
215
|
```python
|
91
216
|
from djresttoolkit.mail import EmailSender, EmailContent, EmailTemplate
|
@@ -101,7 +226,7 @@ Send templated emails.
|
|
101
226
|
EmailSender(email_content: EmailContent | EmailContentDict)
|
102
227
|
```
|
103
228
|
|
104
|
-
#### Methods
|
229
|
+
#### EmailSender Methods
|
105
230
|
|
106
231
|
```python
|
107
232
|
send(to: list[str], exceptions: bool = False) -> bool
|
@@ -134,7 +259,7 @@ EmailSender(content).send(to=["user@example.com"])
|
|
134
259
|
|
135
260
|
- `text`, `html` — template file paths
|
136
261
|
|
137
|
-
###
|
262
|
+
### 5. Custom DRF Exception Handler
|
138
263
|
|
139
264
|
```python
|
140
265
|
from djresttoolkit.views import exception_handler
|
@@ -148,12 +273,12 @@ A DRF exception handler that:
|
|
148
273
|
- Adds throttling support (defaults to `AnonRateThrottle`).
|
149
274
|
- Returns **429 Too Many Requests** with `retry_after` if throttle limit is exceeded.
|
150
275
|
|
151
|
-
#### Parameters
|
276
|
+
#### Exception Handler Parameters
|
152
277
|
|
153
278
|
- `exc`: Exception object.
|
154
279
|
- `context`: DRF context dictionary containing `"request"` and `"view"`.
|
155
280
|
|
156
|
-
#### Returns
|
281
|
+
#### Returns Type of Exception Handler
|
157
282
|
|
158
283
|
- `Response` — DRF Response object (with throttling info if applicable), or `None`.
|
159
284
|
|
@@ -174,7 +299,7 @@ REST_FRAMEWORK = {
|
|
174
299
|
- Tracks requests in cache and calculates `retry_after`.
|
175
300
|
- Cleans expired timestamps automatically.
|
176
301
|
|
177
|
-
###
|
302
|
+
### 6. Response Time Middleware
|
178
303
|
|
179
304
|
```python
|
180
305
|
from djresttoolkit.middlewares import ResponseTimeMiddleware
|
@@ -192,7 +317,7 @@ ResponseTimeMiddleware(get_response: Callable[[HttpRequest], HttpResponse])
|
|
192
317
|
|
193
318
|
- `get_response`: The next middleware or view callable.
|
194
319
|
|
195
|
-
#### Usage
|
320
|
+
#### Response Time Middleware Usage
|
196
321
|
|
197
322
|
Add it to your Django `MIDDLEWARE` in `settings.py`:
|
198
323
|
|
@@ -221,7 +346,7 @@ X-Response-Time: 0.01234 seconds
|
|
221
346
|
INFO: Request processed in 0.01234 seconds
|
222
347
|
```
|
223
348
|
|
224
|
-
###
|
349
|
+
### 7. Throttle Utilities
|
225
350
|
|
226
351
|
#### `ThrottleInfoJSONRenderer`
|
227
352
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: djresttoolkit
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.8.0
|
4
4
|
Summary: A collection of Django and DRF utilities to simplify API development.
|
5
5
|
Project-URL: Homepage, https://github.com/shaileshpandit141/djresttoolkit
|
6
6
|
Project-URL: Documentation, https://shaileshpandit141.github.io/djresttoolkit
|
@@ -47,7 +47,9 @@ Classifier: Topic :: Utilities
|
|
47
47
|
Classifier: Typing :: Typed
|
48
48
|
Requires-Python: >=3.13
|
49
49
|
Requires-Dist: faker>=37.5.3
|
50
|
+
Requires-Dist: pydantic-settings>=2.10.1
|
50
51
|
Requires-Dist: pydantic>=2.11.7
|
52
|
+
Requires-Dist: pyyaml>=6.0.2
|
51
53
|
Provides-Extra: dev
|
52
54
|
Requires-Dist: mypy; extra == 'dev'
|
53
55
|
Requires-Dist: pytest; extra == 'dev'
|
@@ -141,7 +143,132 @@ python manage.py dbseed --count 10
|
|
141
143
|
python manage.py dbseed --model User --seed 42
|
142
144
|
```
|
143
145
|
|
144
|
-
|
146
|
+
Here’s a **concise API reference** for your database flush management command for `djresttoolkit`:
|
147
|
+
|
148
|
+
---
|
149
|
+
|
150
|
+
### 2. DB Flush Command
|
151
|
+
|
152
|
+
```python
|
153
|
+
from djresttoolkit.management.commands import flush
|
154
|
+
```
|
155
|
+
|
156
|
+
#### `manage.py dbflush`
|
157
|
+
|
158
|
+
Command to **delete all records** from the database for all models or a specific model and **reset auto-increment IDs**.
|
159
|
+
|
160
|
+
#### Usage
|
161
|
+
|
162
|
+
```bash
|
163
|
+
python manage.py flush [--model ModelName] [--yes]
|
164
|
+
```
|
165
|
+
|
166
|
+
#### dbflush command options
|
167
|
+
|
168
|
+
- `--model`: Name of the model to flush (case-sensitive, e.g., `User`). If omitted, flushes all models.
|
169
|
+
- `--yes`: Skip confirmation prompt. Without this, the command asks for confirmation before deleting.
|
170
|
+
|
171
|
+
#### dbflush command behavior
|
172
|
+
|
173
|
+
- Deletes all records for the specified model or all models.
|
174
|
+
- Resets primary key sequences for supported databases:
|
175
|
+
|
176
|
+
- PostgreSQL: `ALTER SEQUENCE ... RESTART WITH 1`
|
177
|
+
- SQLite: Deletes from `sqlite_sequence` table
|
178
|
+
- Others: Logs a warning (not implemented).
|
179
|
+
- Uses transactions to ensure safe operations.
|
180
|
+
|
181
|
+
#### dbflush command example
|
182
|
+
|
183
|
+
```bash
|
184
|
+
# Flush all models with confirmation
|
185
|
+
python manage.py dbflush
|
186
|
+
|
187
|
+
# Flush a specific model (User) with confirmation
|
188
|
+
python manage.py dbflush --model User
|
189
|
+
|
190
|
+
# Flush all models without prompt
|
191
|
+
python manage.py dbflush --yes
|
192
|
+
```
|
193
|
+
|
194
|
+
#### Output
|
195
|
+
|
196
|
+
```bash
|
197
|
+
Flushed 10 records from model "User" and reset IDs.
|
198
|
+
```
|
199
|
+
|
200
|
+
or
|
201
|
+
|
202
|
+
```bash
|
203
|
+
Flushed 120 records from all models and reset IDs.
|
204
|
+
```
|
205
|
+
|
206
|
+
### 3. EnvBaseSettings
|
207
|
+
|
208
|
+
```python
|
209
|
+
from djresttoolkit.envconfig import EnvBaseSettings
|
210
|
+
```
|
211
|
+
|
212
|
+
#### `EnvBaseSettings`
|
213
|
+
|
214
|
+
A **base settings class** for managing application configuration using:
|
215
|
+
|
216
|
+
- YAML files (default `.environ.yaml`)
|
217
|
+
- Environment variables (default `.env`)
|
218
|
+
|
219
|
+
Supports **nested configuration** using double underscores (`__`) in environment variable names.
|
220
|
+
|
221
|
+
#### Class Attributes
|
222
|
+
|
223
|
+
| Attribute | Type | Default | Description |
|
224
|
+
| -------------- | -------------------- | --------------- | ------------------------------------------------------------------ |
|
225
|
+
| `env_file` | `str` | `.env` | Environment variable file path. |
|
226
|
+
| `yaml_file` | `str` | `.environ.yaml` | YAML configuration file path. |
|
227
|
+
| `model_config` | `SettingsConfigDict` | — | Pydantic settings configuration (file encoding, nested delimiter). |
|
228
|
+
|
229
|
+
#### Methods
|
230
|
+
|
231
|
+
#### `load(cls, *, env_file: str | None = None, ymal_file: str | None = None, warning: bool = True) -> EnvBaseSettings`
|
232
|
+
|
233
|
+
Loads configuration from **YAML first**, then overrides with **environment variables**.
|
234
|
+
|
235
|
+
#### Parameters
|
236
|
+
|
237
|
+
- `env_file` — Optional custom `.env` file path.
|
238
|
+
- `ymal_file` — Optional custom YAML file path.
|
239
|
+
- `warning` — Emit a warning if YAML file is missing (default `True`).
|
240
|
+
|
241
|
+
#### Returns
|
242
|
+
|
243
|
+
- Instance of `EnvBaseSettings` (or subclass) with loaded configuration.
|
244
|
+
|
245
|
+
#### Raises
|
246
|
+
|
247
|
+
- `UserWarning` if YAML file not found and `warning=True`.
|
248
|
+
|
249
|
+
### Usage Example
|
250
|
+
|
251
|
+
```python
|
252
|
+
from djresttoolkit.envconfig import EnvBaseSettings
|
253
|
+
|
254
|
+
class EnvSettings(EnvBaseSettings):
|
255
|
+
debug: bool = False
|
256
|
+
database_url: str
|
257
|
+
|
258
|
+
# Load settings
|
259
|
+
settings = EnvSettings.load(warning=False)
|
260
|
+
|
261
|
+
print(settings.debug)
|
262
|
+
print(settings.database_url)
|
263
|
+
```
|
264
|
+
|
265
|
+
#### Features
|
266
|
+
|
267
|
+
- Prioritizes `.env` variables over YAML.
|
268
|
+
- Supports nested keys: `DATABASE__HOST` → `settings.database.host`.
|
269
|
+
- Designed to be subclassed for project-specific settings.
|
270
|
+
|
271
|
+
### 4. EmailSender
|
145
272
|
|
146
273
|
```python
|
147
274
|
from djresttoolkit.mail import EmailSender, EmailContent, EmailTemplate
|
@@ -157,7 +284,7 @@ Send templated emails.
|
|
157
284
|
EmailSender(email_content: EmailContent | EmailContentDict)
|
158
285
|
```
|
159
286
|
|
160
|
-
#### Methods
|
287
|
+
#### EmailSender Methods
|
161
288
|
|
162
289
|
```python
|
163
290
|
send(to: list[str], exceptions: bool = False) -> bool
|
@@ -190,7 +317,7 @@ EmailSender(content).send(to=["user@example.com"])
|
|
190
317
|
|
191
318
|
- `text`, `html` — template file paths
|
192
319
|
|
193
|
-
###
|
320
|
+
### 5. Custom DRF Exception Handler
|
194
321
|
|
195
322
|
```python
|
196
323
|
from djresttoolkit.views import exception_handler
|
@@ -204,12 +331,12 @@ A DRF exception handler that:
|
|
204
331
|
- Adds throttling support (defaults to `AnonRateThrottle`).
|
205
332
|
- Returns **429 Too Many Requests** with `retry_after` if throttle limit is exceeded.
|
206
333
|
|
207
|
-
#### Parameters
|
334
|
+
#### Exception Handler Parameters
|
208
335
|
|
209
336
|
- `exc`: Exception object.
|
210
337
|
- `context`: DRF context dictionary containing `"request"` and `"view"`.
|
211
338
|
|
212
|
-
#### Returns
|
339
|
+
#### Returns Type of Exception Handler
|
213
340
|
|
214
341
|
- `Response` — DRF Response object (with throttling info if applicable), or `None`.
|
215
342
|
|
@@ -230,7 +357,7 @@ REST_FRAMEWORK = {
|
|
230
357
|
- Tracks requests in cache and calculates `retry_after`.
|
231
358
|
- Cleans expired timestamps automatically.
|
232
359
|
|
233
|
-
###
|
360
|
+
### 6. Response Time Middleware
|
234
361
|
|
235
362
|
```python
|
236
363
|
from djresttoolkit.middlewares import ResponseTimeMiddleware
|
@@ -248,7 +375,7 @@ ResponseTimeMiddleware(get_response: Callable[[HttpRequest], HttpResponse])
|
|
248
375
|
|
249
376
|
- `get_response`: The next middleware or view callable.
|
250
377
|
|
251
|
-
#### Usage
|
378
|
+
#### Response Time Middleware Usage
|
252
379
|
|
253
380
|
Add it to your Django `MIDDLEWARE` in `settings.py`:
|
254
381
|
|
@@ -277,7 +404,7 @@ X-Response-Time: 0.01234 seconds
|
|
277
404
|
INFO: Request processed in 0.01234 seconds
|
278
405
|
```
|
279
406
|
|
280
|
-
###
|
407
|
+
### 7. Throttle Utilities
|
281
408
|
|
282
409
|
#### `ThrottleInfoJSONRenderer`
|
283
410
|
|
@@ -1,20 +1,24 @@
|
|
1
1
|
LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
|
2
|
-
README.md,sha256=
|
2
|
+
README.md,sha256=9S8AiRr4U5uA-YrgtQbUZiYpbg4rT_UejlDGhJ2WYzM,10558
|
3
3
|
demo/staticfiles/admin/img/LICENSE,sha256=0RT6_zSIwWwxmzI13EH5AjnT1j2YU3MwM9j3U19cAAQ,1081
|
4
4
|
src/djresttoolkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
src/djresttoolkit/admin.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
6
|
src/djresttoolkit/apps.py,sha256=nKb5GUIEhAB3IL3lTmEXNc5XuvvaZupH-1CCuYKFrEQ,158
|
7
7
|
src/djresttoolkit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
src/djresttoolkit/dbseed/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
src/djresttoolkit/dbseed/models/__init__.py,sha256=
|
9
|
+
src/djresttoolkit/dbseed/models/__init__.py,sha256=uuynQIcfVqEaZN9hF_caI24zm8az23JdXLDrv7xOKTQ,180
|
10
|
+
src/djresttoolkit/dbseed/models/_choice_field.py,sha256=T7LAzbyXqlYp2mtCAKL8E1Da_MEh9RzgLZrFJ7fa4gM,446
|
10
11
|
src/djresttoolkit/dbseed/models/_gen.py,sha256=qBPQaLvh1rcEam0YmE4JBJqpa-Vv5IFlIIagkEMHDVw,206
|
11
12
|
src/djresttoolkit/dbseed/models/_seed_model.py,sha256=0cmbi0VNKjmJbwhjeCFsvb3iKYjok6TJOk6Y2MF_3N4,2443
|
13
|
+
src/djresttoolkit/envconfig/__init__.py,sha256=PcLaPaVfQmz3-4m6SwoOQF2W4U7F0agBGJ4Qjqbcyfw,74
|
14
|
+
src/djresttoolkit/envconfig/_env_settings.py,sha256=cKGDLo7WU0wzQGkWSwgrUxGCb0sT111JUt4HGlDVSxo,3221
|
12
15
|
src/djresttoolkit/mail/__init__.py,sha256=tB9SdMlhfWQ640q4aobZ0H1c7fTWalpDL2I-onkr2VI,268
|
13
16
|
src/djresttoolkit/mail/_email_sender.py,sha256=bPMqgD5HibJcOZgO6xxHOhdK9HEhnGNC6BoMPpo-h7k,3096
|
14
17
|
src/djresttoolkit/mail/_models.py,sha256=of5KsLGvsN2OWgDYgdtLEijulg817TXgsLKuUdsnDQc,1447
|
15
18
|
src/djresttoolkit/mail/_types.py,sha256=zf6CcXR1ei_UmZ1nLAJa378OAJ6ftnBICqEOkzXPNw8,646
|
16
19
|
src/djresttoolkit/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
20
|
src/djresttoolkit/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
+
src/djresttoolkit/management/commands/dbflush.py,sha256=v7rXcuNQDiXLV7p0xzKMNXVeWAN7QKmq2qQQAbhHEEw,3423
|
18
22
|
src/djresttoolkit/management/commands/dbseed.py,sha256=sY87TvvzECG7aQXxsDjr45VzCzJpofLacBK49EYFK8M,4225
|
19
23
|
src/djresttoolkit/middlewares/__init__.py,sha256=GZHU3Yy4xXoEi62tHn0UJNxN6XgGM2_HES8Bt5AS5Lk,100
|
20
24
|
src/djresttoolkit/middlewares/_response_time_middleware.py,sha256=1wCwdkW5Ng6HJo8zx0F7ylms84OGP-1K0kbyG6Vacuk,908
|
@@ -27,8 +31,8 @@ src/djresttoolkit/throttling/_throttle_inspector.py,sha256=Kss6ZxKy-EXq9UGaGprGD
|
|
27
31
|
src/djresttoolkit/views/__init__.py,sha256=XrxBrs6sH4HmUzp41omcmy_y94pSaXAVn01ttQ022-4,76
|
28
32
|
src/djresttoolkit/views/_exceptions/__init__.py,sha256=DrCUxuPNyBR4WhzNutn5HDxLa--q51ykIxSG7_bFsOI,83
|
29
33
|
src/djresttoolkit/views/_exceptions/_exception_handler.py,sha256=_o7If47bzWLl57LeSXSWsIDsJGo2RIpwYAwNQ-hsHVY,2839
|
30
|
-
djresttoolkit-0.
|
31
|
-
djresttoolkit-0.
|
32
|
-
djresttoolkit-0.
|
33
|
-
djresttoolkit-0.
|
34
|
-
djresttoolkit-0.
|
34
|
+
djresttoolkit-0.8.0.dist-info/METADATA,sha256=qCwxDQnmpbQygUL7gytkkO826sOs9Zm8Xy_NXmlLvQY,13567
|
35
|
+
djresttoolkit-0.8.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
36
|
+
djresttoolkit-0.8.0.dist-info/entry_points.txt,sha256=YMhfTF-7mYppO8QqqWnvR_hyMWvoYxD6XI94_ViFu3k,60
|
37
|
+
djresttoolkit-0.8.0.dist-info/licenses/LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
|
38
|
+
djresttoolkit-0.8.0.dist-info/RECORD,,
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import random
|
2
|
+
|
3
|
+
from pydantic import Field
|
4
|
+
|
5
|
+
|
6
|
+
def choice_field[T](choices: list[T]) -> T:
|
7
|
+
"""
|
8
|
+
Creates a field with a default value randomly selected from the provided choices.
|
9
|
+
Args:
|
10
|
+
choices (list[T]): A list of possible values for the field.
|
11
|
+
Returns:
|
12
|
+
T: A field with a default value randomly chosen from the given choices.
|
13
|
+
"""
|
14
|
+
|
15
|
+
return Field(
|
16
|
+
default_factory=lambda: random.choice(seq=choices),
|
17
|
+
)
|
@@ -0,0 +1,84 @@
|
|
1
|
+
import warnings
|
2
|
+
from pathlib import Path
|
3
|
+
from typing import Any, ClassVar
|
4
|
+
|
5
|
+
import yaml
|
6
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
7
|
+
|
8
|
+
|
9
|
+
class EnvBaseSettings(BaseSettings):
|
10
|
+
""" "
|
11
|
+
EnvBaseSettings is a base settings class for managing application configuration
|
12
|
+
using both YAML files and environment variables.
|
13
|
+
This class is designed to load configuration values from a YAML file first,
|
14
|
+
and then override those values with environment variables if present. It supports
|
15
|
+
nested configuration using a double underscore (`__`) as the delimiter in
|
16
|
+
environment variable names, allowing for hierarchical settings.
|
17
|
+
|
18
|
+
Class Attributes:
|
19
|
+
env_file (str): The default filename for the environment variables file (default: ".env").
|
20
|
+
yaml_file (str): The default filename for the YAML configuration file (default: ".environ.yaml").
|
21
|
+
model_config (SettingsConfigDict): Configuration for environment variable parsing, including file encoding and nested delimiter.
|
22
|
+
|
23
|
+
Methods:
|
24
|
+
load(cls, *, env_file: str | None = None, ymal_file: str | None = None, warning: bool = True) -> "EnvBaseSettings":
|
25
|
+
Loads configuration from a YAML file (if it exists), then overrides with environment variables.
|
26
|
+
- env_file: Optional custom path to the .env file.
|
27
|
+
- ymal_file: Optional custom path to the YAML file.
|
28
|
+
- warning: If True, emits a warning if the YAML file is not found.
|
29
|
+
Returns an instance of EnvBaseSettings with the loaded configuration.
|
30
|
+
|
31
|
+
Usage:
|
32
|
+
- Define your settings as subclasses of EnvBaseSettings.
|
33
|
+
- Call `YourSettingsClass.load()` to load configuration from files and environment variables.
|
34
|
+
- Supports nested configuration via double underscore in environment variable names (e.g., `DATABASE__HOST`).
|
35
|
+
|
36
|
+
Raises:
|
37
|
+
- UserWarning: If the YAML file is not found and `warning` is True.
|
38
|
+
|
39
|
+
Example:
|
40
|
+
```python
|
41
|
+
from djresttoolkit.envconfig import EnvBaseSettings
|
42
|
+
|
43
|
+
class EnvSettings(EnvBaseSettings):
|
44
|
+
debug: bool = False
|
45
|
+
database_url: str
|
46
|
+
|
47
|
+
settings = EnvSettings.load(warning=False)
|
48
|
+
```
|
49
|
+
|
50
|
+
"""
|
51
|
+
|
52
|
+
env_file: ClassVar[str] = ".env"
|
53
|
+
yaml_file: ClassVar[str] = ".environ.yaml"
|
54
|
+
|
55
|
+
model_config = SettingsConfigDict(
|
56
|
+
env_file=env_file,
|
57
|
+
env_file_encoding="utf-8",
|
58
|
+
env_nested_delimiter="__",
|
59
|
+
)
|
60
|
+
|
61
|
+
@classmethod
|
62
|
+
def load(
|
63
|
+
cls,
|
64
|
+
*,
|
65
|
+
env_file: str | None = None,
|
66
|
+
ymal_file: str | None = None,
|
67
|
+
warning: bool = True,
|
68
|
+
) -> "EnvBaseSettings":
|
69
|
+
"""Load from YAML first, then override with .env."""
|
70
|
+
if env_file:
|
71
|
+
cls.env_file = env_file
|
72
|
+
if ymal_file:
|
73
|
+
cls.yaml_file = ymal_file
|
74
|
+
|
75
|
+
config_file = Path(cls.yaml_file)
|
76
|
+
yaml_data: dict[str, Any] = {}
|
77
|
+
if config_file.exists():
|
78
|
+
with config_file.open("r") as f:
|
79
|
+
yaml_data = yaml.safe_load(f) or {}
|
80
|
+
elif warning:
|
81
|
+
msg: str = f"Config file {config_file} not found, using only env vars."
|
82
|
+
warnings.warn(msg, UserWarning, stacklevel=1)
|
83
|
+
|
84
|
+
return cls(**yaml_data)
|
@@ -0,0 +1,94 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
from django.apps import apps
|
4
|
+
from django.core.management.base import BaseCommand, CommandError, CommandParser
|
5
|
+
from django.db import connection, transaction
|
6
|
+
|
7
|
+
|
8
|
+
class Command(BaseCommand):
|
9
|
+
help = "Flush database records for all models or a specific model"
|
10
|
+
|
11
|
+
def add_arguments(self, parser: CommandParser) -> None:
|
12
|
+
parser.add_argument(
|
13
|
+
"--model",
|
14
|
+
type=str,
|
15
|
+
help="Specify the model name to flush records (case-sensitive, e.g., User)",
|
16
|
+
)
|
17
|
+
parser.add_argument(
|
18
|
+
"--yes",
|
19
|
+
action="store_true",
|
20
|
+
help="Confirm flush without prompt",
|
21
|
+
)
|
22
|
+
|
23
|
+
def handle(self, *args: Any, **options: Any) -> None:
|
24
|
+
"""Handle the flushing of database records and reset IDs."""
|
25
|
+
|
26
|
+
model_name = options.get("model")
|
27
|
+
confirm = options.get("yes", False)
|
28
|
+
|
29
|
+
if not confirm:
|
30
|
+
prompt = "Are you sure you want to flush "
|
31
|
+
prompt += f"the model '{model_name}'" if model_name else "all models"
|
32
|
+
prompt += "? [y/n]: "
|
33
|
+
user_input = input(prompt)
|
34
|
+
if user_input.lower() not in ["y", "yes"]:
|
35
|
+
self.stdout.write(self.style.WARNING("Operation cancelled."))
|
36
|
+
return
|
37
|
+
|
38
|
+
def reset_sequence(table_name: str) -> None:
|
39
|
+
"""Reset auto-increment ID sequence for supported databases."""
|
40
|
+
with connection.cursor() as cursor:
|
41
|
+
if connection.vendor == "postgresql":
|
42
|
+
cursor.execute(
|
43
|
+
f'ALTER SEQUENCE "{table_name}_id_seq" RESTART WITH 1;'
|
44
|
+
)
|
45
|
+
elif connection.vendor == "sqlite":
|
46
|
+
cursor.execute(
|
47
|
+
f"DELETE FROM sqlite_sequence WHERE name='{table_name}';"
|
48
|
+
)
|
49
|
+
else:
|
50
|
+
self.stdout.write(
|
51
|
+
self.style.WARNING(
|
52
|
+
f"ID reset not implemented for {connection.vendor}."
|
53
|
+
)
|
54
|
+
)
|
55
|
+
|
56
|
+
if model_name:
|
57
|
+
# Find the model automatically across all apps
|
58
|
+
model = None
|
59
|
+
for m in apps.get_models():
|
60
|
+
if m.__name__ == model_name:
|
61
|
+
model = m
|
62
|
+
break
|
63
|
+
|
64
|
+
if not model:
|
65
|
+
raise CommandError(
|
66
|
+
f'Model "{model_name}" not found in any installed app.'
|
67
|
+
)
|
68
|
+
|
69
|
+
table_name = model._meta.db_table
|
70
|
+
with transaction.atomic():
|
71
|
+
deleted_count, _ = model.objects.all().delete()
|
72
|
+
reset_sequence(table_name)
|
73
|
+
|
74
|
+
self.stdout.write(
|
75
|
+
self.style.SUCCESS(
|
76
|
+
f'Flushed {deleted_count} records from model "{model_name}" and reset IDs.'
|
77
|
+
)
|
78
|
+
)
|
79
|
+
|
80
|
+
else:
|
81
|
+
# Flush all models
|
82
|
+
total_deleted = 0
|
83
|
+
with transaction.atomic():
|
84
|
+
for model in apps.get_models():
|
85
|
+
table_name = model._meta.db_table
|
86
|
+
deleted_count, _ = model.objects.all().delete()
|
87
|
+
total_deleted += deleted_count
|
88
|
+
reset_sequence(table_name)
|
89
|
+
|
90
|
+
self.stdout.write(
|
91
|
+
self.style.SUCCESS(
|
92
|
+
f"Flushed {total_deleted} records from all models and reset IDs."
|
93
|
+
)
|
94
|
+
)
|
File without changes
|
File without changes
|
File without changes
|