djresttoolkit 0.6.0__py3-none-any.whl → 0.6.2__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 +62 -7
- {djresttoolkit-0.6.0.dist-info → djresttoolkit-0.6.2.dist-info}/METADATA +63 -8
- {djresttoolkit-0.6.0.dist-info → djresttoolkit-0.6.2.dist-info}/RECORD +9 -9
- src/djresttoolkit/dbseed/models/__init__.py +2 -2
- src/djresttoolkit/dbseed/models/{_base_seed_model.py → _seed_model.py} +19 -13
- src/djresttoolkit/management/commands/dbseed.py +6 -6
- {djresttoolkit-0.6.0.dist-info → djresttoolkit-0.6.2.dist-info}/WHEEL +0 -0
- {djresttoolkit-0.6.0.dist-info → djresttoolkit-0.6.2.dist-info}/entry_points.txt +0 -0
- {djresttoolkit-0.6.0.dist-info → djresttoolkit-0.6.2.dist-info}/licenses/LICENSE +0 -0
README.md
CHANGED
@@ -28,9 +28,64 @@ djresttoolkit is a collection of utilities and helpers for Django and Django RES
|
|
28
28
|
pip install djresttoolkit
|
29
29
|
````
|
30
30
|
|
31
|
-
## 📚 API Reference
|
31
|
+
## 📚 All API Reference
|
32
32
|
|
33
|
-
### 1.
|
33
|
+
### 1. DB Seed Utilities
|
34
|
+
|
35
|
+
#### `Generator`
|
36
|
+
|
37
|
+
```python
|
38
|
+
from djresttoolkit.dbseed.models import Generator, Gen, Field
|
39
|
+
```
|
40
|
+
|
41
|
+
- `Gen`: Pre-initialized **Faker** instance for generating fake data.
|
42
|
+
- `Field`: Alias for `pydantic.Field` to define seed model fields.
|
43
|
+
|
44
|
+
#### Example
|
45
|
+
|
46
|
+
```python
|
47
|
+
from djresttoolkit.dbseed.models import SeedModel
|
48
|
+
from myapp.models import User
|
49
|
+
|
50
|
+
class UserSeedModel(SeedModel):
|
51
|
+
__model__ = User
|
52
|
+
|
53
|
+
username: str = Field(default_factory=lambda: Gen.user_name())
|
54
|
+
email: str = Field(default_factory=lambda: Gen.email())
|
55
|
+
```
|
56
|
+
|
57
|
+
#### `manage.py` Command: `dbseed`
|
58
|
+
|
59
|
+
Seed the database from all `dbseed` directories in installed apps.
|
60
|
+
|
61
|
+
```bash
|
62
|
+
python manage.py dbseed [--count 5] [--model User] [--seed 42]
|
63
|
+
```
|
64
|
+
|
65
|
+
#### Options
|
66
|
+
|
67
|
+
- `--count`: Number of records per model (default: 5).
|
68
|
+
- `--model`: Specific model name to seed (optional).
|
69
|
+
- `--seed`: Faker seed for reproducible data (optional).
|
70
|
+
|
71
|
+
#### Behavior
|
72
|
+
|
73
|
+
- Auto-discovers all `dbseed` models in installed apps.
|
74
|
+
- Handles ForeignKey, OneToOneField, and ManyToMany relationships.
|
75
|
+
- Uses transactions to ensure safe creation of records.
|
76
|
+
- Logs errors for failed instance creation but continues seeding.
|
77
|
+
|
78
|
+
#### Command Example
|
79
|
+
|
80
|
+
```bash
|
81
|
+
# Seed 10 records for all models
|
82
|
+
python manage.py dbseed --count 10
|
83
|
+
|
84
|
+
# Seed only the User model with fixed Faker seed
|
85
|
+
python manage.py dbseed --model User --seed 42
|
86
|
+
```
|
87
|
+
|
88
|
+
### 2. EmailSender
|
34
89
|
|
35
90
|
```python
|
36
91
|
from djresttoolkit.mail import EmailSender, EmailContent, EmailTemplate
|
@@ -56,7 +111,7 @@ send(to: list[str], exceptions: bool = False) -> bool
|
|
56
111
|
- `exceptions`: raise on error if `True`, else logs error
|
57
112
|
- Returns `True` if sent, `False` on failure
|
58
113
|
|
59
|
-
#### Example
|
114
|
+
#### Example for sending an email
|
60
115
|
|
61
116
|
```python
|
62
117
|
content = EmailContent(
|
@@ -79,7 +134,7 @@ EmailSender(content).send(to=["user@example.com"])
|
|
79
134
|
|
80
135
|
- `text`, `html` — template file paths
|
81
136
|
|
82
|
-
###
|
137
|
+
### 3. Custom DRF Exception Handler
|
83
138
|
|
84
139
|
```python
|
85
140
|
from djresttoolkit.views import exception_handler
|
@@ -119,7 +174,7 @@ REST_FRAMEWORK = {
|
|
119
174
|
- Tracks requests in cache and calculates `retry_after`.
|
120
175
|
- Cleans expired timestamps automatically.
|
121
176
|
|
122
|
-
###
|
177
|
+
### 4. Response Time Middleware
|
123
178
|
|
124
179
|
```python
|
125
180
|
from djresttoolkit.middlewares import ResponseTimeMiddleware
|
@@ -148,7 +203,7 @@ MIDDLEWARE = [
|
|
148
203
|
]
|
149
204
|
```
|
150
205
|
|
151
|
-
#### Behavior
|
206
|
+
#### Response Time Middleware Behavior
|
152
207
|
|
153
208
|
- Measures the time taken to process each request.
|
154
209
|
- Adds a header `X-Response-Time` to each HTTP response.
|
@@ -166,7 +221,7 @@ X-Response-Time: 0.01234 seconds
|
|
166
221
|
INFO: Request processed in 0.01234 seconds
|
167
222
|
```
|
168
223
|
|
169
|
-
###
|
224
|
+
### 5. Throttle Utilities
|
170
225
|
|
171
226
|
#### `ThrottleInfoJSONRenderer`
|
172
227
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: djresttoolkit
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.2
|
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
|
@@ -84,9 +84,64 @@ djresttoolkit is a collection of utilities and helpers for Django and Django RES
|
|
84
84
|
pip install djresttoolkit
|
85
85
|
````
|
86
86
|
|
87
|
-
## 📚 API Reference
|
87
|
+
## 📚 All API Reference
|
88
88
|
|
89
|
-
### 1.
|
89
|
+
### 1. DB Seed Utilities
|
90
|
+
|
91
|
+
#### `Generator`
|
92
|
+
|
93
|
+
```python
|
94
|
+
from djresttoolkit.dbseed.models import Generator, Gen, Field
|
95
|
+
```
|
96
|
+
|
97
|
+
- `Gen`: Pre-initialized **Faker** instance for generating fake data.
|
98
|
+
- `Field`: Alias for `pydantic.Field` to define seed model fields.
|
99
|
+
|
100
|
+
#### Example
|
101
|
+
|
102
|
+
```python
|
103
|
+
from djresttoolkit.dbseed.models import SeedModel
|
104
|
+
from myapp.models import User
|
105
|
+
|
106
|
+
class UserSeedModel(SeedModel):
|
107
|
+
__model__ = User
|
108
|
+
|
109
|
+
username: str = Field(default_factory=lambda: Gen.user_name())
|
110
|
+
email: str = Field(default_factory=lambda: Gen.email())
|
111
|
+
```
|
112
|
+
|
113
|
+
#### `manage.py` Command: `dbseed`
|
114
|
+
|
115
|
+
Seed the database from all `dbseed` directories in installed apps.
|
116
|
+
|
117
|
+
```bash
|
118
|
+
python manage.py dbseed [--count 5] [--model User] [--seed 42]
|
119
|
+
```
|
120
|
+
|
121
|
+
#### Options
|
122
|
+
|
123
|
+
- `--count`: Number of records per model (default: 5).
|
124
|
+
- `--model`: Specific model name to seed (optional).
|
125
|
+
- `--seed`: Faker seed for reproducible data (optional).
|
126
|
+
|
127
|
+
#### Behavior
|
128
|
+
|
129
|
+
- Auto-discovers all `dbseed` models in installed apps.
|
130
|
+
- Handles ForeignKey, OneToOneField, and ManyToMany relationships.
|
131
|
+
- Uses transactions to ensure safe creation of records.
|
132
|
+
- Logs errors for failed instance creation but continues seeding.
|
133
|
+
|
134
|
+
#### Command Example
|
135
|
+
|
136
|
+
```bash
|
137
|
+
# Seed 10 records for all models
|
138
|
+
python manage.py dbseed --count 10
|
139
|
+
|
140
|
+
# Seed only the User model with fixed Faker seed
|
141
|
+
python manage.py dbseed --model User --seed 42
|
142
|
+
```
|
143
|
+
|
144
|
+
### 2. EmailSender
|
90
145
|
|
91
146
|
```python
|
92
147
|
from djresttoolkit.mail import EmailSender, EmailContent, EmailTemplate
|
@@ -112,7 +167,7 @@ send(to: list[str], exceptions: bool = False) -> bool
|
|
112
167
|
- `exceptions`: raise on error if `True`, else logs error
|
113
168
|
- Returns `True` if sent, `False` on failure
|
114
169
|
|
115
|
-
#### Example
|
170
|
+
#### Example for sending an email
|
116
171
|
|
117
172
|
```python
|
118
173
|
content = EmailContent(
|
@@ -135,7 +190,7 @@ EmailSender(content).send(to=["user@example.com"])
|
|
135
190
|
|
136
191
|
- `text`, `html` — template file paths
|
137
192
|
|
138
|
-
###
|
193
|
+
### 3. Custom DRF Exception Handler
|
139
194
|
|
140
195
|
```python
|
141
196
|
from djresttoolkit.views import exception_handler
|
@@ -175,7 +230,7 @@ REST_FRAMEWORK = {
|
|
175
230
|
- Tracks requests in cache and calculates `retry_after`.
|
176
231
|
- Cleans expired timestamps automatically.
|
177
232
|
|
178
|
-
###
|
233
|
+
### 4. Response Time Middleware
|
179
234
|
|
180
235
|
```python
|
181
236
|
from djresttoolkit.middlewares import ResponseTimeMiddleware
|
@@ -204,7 +259,7 @@ MIDDLEWARE = [
|
|
204
259
|
]
|
205
260
|
```
|
206
261
|
|
207
|
-
#### Behavior
|
262
|
+
#### Response Time Middleware Behavior
|
208
263
|
|
209
264
|
- Measures the time taken to process each request.
|
210
265
|
- Adds a header `X-Response-Time` to each HTTP response.
|
@@ -222,7 +277,7 @@ X-Response-Time: 0.01234 seconds
|
|
222
277
|
INFO: Request processed in 0.01234 seconds
|
223
278
|
```
|
224
279
|
|
225
|
-
###
|
280
|
+
### 5. Throttle Utilities
|
226
281
|
|
227
282
|
#### `ThrottleInfoJSONRenderer`
|
228
283
|
|
@@ -1,21 +1,21 @@
|
|
1
1
|
LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
|
2
|
-
README.md,sha256=
|
2
|
+
README.md,sha256=q-R5E_ZZPZt6vLW4TL-HA8M601_vQrI53IZ-dIAgD9E,6983
|
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=
|
10
|
-
src/djresttoolkit/dbseed/models/_base_seed_model.py,sha256=DlbmdafLicKd_ja1AIvKKzyBxdnxdq23zPJwlqxiTl8,2187
|
9
|
+
src/djresttoolkit/dbseed/models/__init__.py,sha256=B2WJqw2ncqf5nNhkM3XDFx13oNg2ccsULUQkFAjOyrY,105
|
11
10
|
src/djresttoolkit/dbseed/models/_gen.py,sha256=qBPQaLvh1rcEam0YmE4JBJqpa-Vv5IFlIIagkEMHDVw,206
|
11
|
+
src/djresttoolkit/dbseed/models/_seed_model.py,sha256=0cmbi0VNKjmJbwhjeCFsvb3iKYjok6TJOk6Y2MF_3N4,2443
|
12
12
|
src/djresttoolkit/mail/__init__.py,sha256=tB9SdMlhfWQ640q4aobZ0H1c7fTWalpDL2I-onkr2VI,268
|
13
13
|
src/djresttoolkit/mail/_email_sender.py,sha256=bPMqgD5HibJcOZgO6xxHOhdK9HEhnGNC6BoMPpo-h7k,3096
|
14
14
|
src/djresttoolkit/mail/_models.py,sha256=of5KsLGvsN2OWgDYgdtLEijulg817TXgsLKuUdsnDQc,1447
|
15
15
|
src/djresttoolkit/mail/_types.py,sha256=zf6CcXR1ei_UmZ1nLAJa378OAJ6ftnBICqEOkzXPNw8,646
|
16
16
|
src/djresttoolkit/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
17
|
src/djresttoolkit/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
-
src/djresttoolkit/management/commands/dbseed.py,sha256=
|
18
|
+
src/djresttoolkit/management/commands/dbseed.py,sha256=sY87TvvzECG7aQXxsDjr45VzCzJpofLacBK49EYFK8M,4225
|
19
19
|
src/djresttoolkit/middlewares/__init__.py,sha256=GZHU3Yy4xXoEi62tHn0UJNxN6XgGM2_HES8Bt5AS5Lk,100
|
20
20
|
src/djresttoolkit/middlewares/_response_time_middleware.py,sha256=1wCwdkW5Ng6HJo8zx0F7ylms84OGP-1K0kbyG6Vacuk,908
|
21
21
|
src/djresttoolkit/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -27,8 +27,8 @@ src/djresttoolkit/throttling/_throttle_inspector.py,sha256=Kss6ZxKy-EXq9UGaGprGD
|
|
27
27
|
src/djresttoolkit/views/__init__.py,sha256=XrxBrs6sH4HmUzp41omcmy_y94pSaXAVn01ttQ022-4,76
|
28
28
|
src/djresttoolkit/views/_exceptions/__init__.py,sha256=DrCUxuPNyBR4WhzNutn5HDxLa--q51ykIxSG7_bFsOI,83
|
29
29
|
src/djresttoolkit/views/_exceptions/_exception_handler.py,sha256=_o7If47bzWLl57LeSXSWsIDsJGo2RIpwYAwNQ-hsHVY,2839
|
30
|
-
djresttoolkit-0.6.
|
31
|
-
djresttoolkit-0.6.
|
32
|
-
djresttoolkit-0.6.
|
33
|
-
djresttoolkit-0.6.
|
34
|
-
djresttoolkit-0.6.
|
30
|
+
djresttoolkit-0.6.2.dist-info/METADATA,sha256=oeLct3kUn0oN2t0SYWXTp-XYRURhNaAcHi7srpU9mE4,9922
|
31
|
+
djresttoolkit-0.6.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
32
|
+
djresttoolkit-0.6.2.dist-info/entry_points.txt,sha256=YMhfTF-7mYppO8QqqWnvR_hyMWvoYxD6XI94_ViFu3k,60
|
33
|
+
djresttoolkit-0.6.2.dist-info/licenses/LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
|
34
|
+
djresttoolkit-0.6.2.dist-info/RECORD,,
|
@@ -1,31 +1,36 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from typing import Any
|
3
|
+
from typing import Any, ClassVar
|
4
4
|
|
5
5
|
from django.db.models import ForeignKey, ManyToManyField, Model, OneToOneField
|
6
6
|
from pydantic import BaseModel
|
7
7
|
|
8
8
|
|
9
|
-
class
|
9
|
+
class SeedModel(BaseModel):
|
10
10
|
"""
|
11
11
|
Base class for all fake data models.
|
12
|
-
Each subclass must define a `
|
12
|
+
Each subclass must define a `__model__` attribute (a Django model).
|
13
13
|
"""
|
14
14
|
|
15
|
-
|
16
|
-
model: type[Model]
|
15
|
+
__model__: ClassVar[type[Model] | None] = None
|
17
16
|
|
18
17
|
def __init_subclass__(cls, **kwargs: Any) -> None:
|
19
18
|
super().__init_subclass__(**kwargs)
|
20
|
-
if not hasattr(cls, "
|
19
|
+
if not hasattr(cls, "__model__"):
|
21
20
|
raise TypeError(
|
22
|
-
f"{cls.__name__} must define a
|
21
|
+
f"{cls.__name__} must define a `__model__` attribute "
|
22
|
+
f"pointing to a Django model"
|
23
23
|
)
|
24
24
|
|
25
25
|
@classmethod
|
26
|
-
def
|
27
|
-
"""Class-level access."""
|
28
|
-
|
26
|
+
def get_model(cls) -> type[Model]:
|
27
|
+
"""Class-level access to the Django model."""
|
28
|
+
if cls.__model__ is None:
|
29
|
+
raise ValueError(
|
30
|
+
f"{cls.__name__} has no `__model__` defined. "
|
31
|
+
"Please set it to a Django model class."
|
32
|
+
)
|
33
|
+
return cls.__model__
|
29
34
|
|
30
35
|
@classmethod
|
31
36
|
def create_instance(cls) -> tuple[dict[str, Any], list[ManyToManyField[Any, Any]]]:
|
@@ -35,13 +40,13 @@ class BaseSeedModel(BaseModel):
|
|
35
40
|
data = cls().model_dump()
|
36
41
|
|
37
42
|
# Handle ForeignKey and OneToOneField
|
38
|
-
for field in cls.
|
43
|
+
for field in cls.get_model()._meta.get_fields():
|
39
44
|
if isinstance(field, (ForeignKey, OneToOneField)):
|
40
45
|
rel_model = field.remote_field.model
|
41
46
|
if rel_model.objects.exists():
|
42
47
|
# For OneToOne, must ensure unique (pick unused relation)
|
43
48
|
if isinstance(field, OneToOneField):
|
44
|
-
used_ids = cls.
|
49
|
+
used_ids = cls.get_model().objects.values_list(
|
45
50
|
field.name, flat=True
|
46
51
|
)
|
47
52
|
available = rel_model.objects.exclude(pk__in=used_ids)
|
@@ -53,7 +58,8 @@ class BaseSeedModel(BaseModel):
|
|
53
58
|
# Collect ManyToMany fields
|
54
59
|
m2m_fields: list[ManyToManyField[Any, Any]] = [
|
55
60
|
field
|
56
|
-
for field in cls.
|
61
|
+
for field in cls.get_model()._meta.get_fields()
|
57
62
|
if isinstance(field, ManyToManyField)
|
58
63
|
]
|
59
64
|
return data, m2m_fields
|
65
|
+
|
@@ -8,7 +8,7 @@ from django.core.management.base import BaseCommand, CommandParser
|
|
8
8
|
from django.db import transaction
|
9
9
|
from django.db.models import Model, QuerySet
|
10
10
|
|
11
|
-
from djresttoolkit.dbseed.models import
|
11
|
+
from djresttoolkit.dbseed.models import SeedModel
|
12
12
|
|
13
13
|
|
14
14
|
class Command(BaseCommand):
|
@@ -48,7 +48,7 @@ class Command(BaseCommand):
|
|
48
48
|
faker = Faker()
|
49
49
|
faker.seed_instance(seed)
|
50
50
|
|
51
|
-
seed_model_classes: list[type[
|
51
|
+
seed_model_classes: list[type[SeedModel]] = []
|
52
52
|
|
53
53
|
# Discover all dbseed dirs in installed apps
|
54
54
|
for app_config in apps.get_app_configs():
|
@@ -67,14 +67,14 @@ class Command(BaseCommand):
|
|
67
67
|
attr = getattr(submodule, attr_name)
|
68
68
|
if (
|
69
69
|
isinstance(attr, type)
|
70
|
-
and issubclass(attr,
|
71
|
-
and attr is not
|
70
|
+
and issubclass(attr, SeedModel)
|
71
|
+
and attr is not SeedModel
|
72
72
|
):
|
73
73
|
# Filter by model name if provided
|
74
74
|
if (
|
75
75
|
not model_name
|
76
76
|
or model_name.lower()
|
77
|
-
== attr.__name__.replace("
|
77
|
+
== attr.__name__.replace("SeedModel", "").lower()
|
78
78
|
):
|
79
79
|
seed_model_classes.append(attr)
|
80
80
|
|
@@ -84,7 +84,7 @@ class Command(BaseCommand):
|
|
84
84
|
|
85
85
|
# Generate fake data for each discovered dbseed model
|
86
86
|
for dbseed_cls in seed_model_classes:
|
87
|
-
django_model = dbseed_cls.
|
87
|
+
django_model = dbseed_cls.get_model()
|
88
88
|
created_count: int = 0
|
89
89
|
|
90
90
|
for _ in range(count):
|
File without changes
|
File without changes
|
File without changes
|