djresttoolkit 0.6.1__py3-none-any.whl → 0.7.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 CHANGED
@@ -28,9 +28,124 @@ 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. EmailSender
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
+ 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. EmailSender
34
149
 
35
150
  ```python
36
151
  from djresttoolkit.mail import EmailSender, EmailContent, EmailTemplate
@@ -56,7 +171,7 @@ send(to: list[str], exceptions: bool = False) -> bool
56
171
  - `exceptions`: raise on error if `True`, else logs error
57
172
  - Returns `True` if sent, `False` on failure
58
173
 
59
- #### Example
174
+ #### Example for sending an email
60
175
 
61
176
  ```python
62
177
  content = EmailContent(
@@ -79,7 +194,7 @@ EmailSender(content).send(to=["user@example.com"])
79
194
 
80
195
  - `text`, `html` — template file paths
81
196
 
82
- ### 2. Custom DRF Exception Handler
197
+ ### 4. Custom DRF Exception Handler
83
198
 
84
199
  ```python
85
200
  from djresttoolkit.views import exception_handler
@@ -119,7 +234,7 @@ REST_FRAMEWORK = {
119
234
  - Tracks requests in cache and calculates `retry_after`.
120
235
  - Cleans expired timestamps automatically.
121
236
 
122
- ### 3. Response Time Middleware
237
+ ### 5. Response Time Middleware
123
238
 
124
239
  ```python
125
240
  from djresttoolkit.middlewares import ResponseTimeMiddleware
@@ -137,7 +252,7 @@ ResponseTimeMiddleware(get_response: Callable[[HttpRequest], HttpResponse])
137
252
 
138
253
  - `get_response`: The next middleware or view callable.
139
254
 
140
- #### Usage
255
+ #### Response Time Middleware Usage
141
256
 
142
257
  Add it to your Django `MIDDLEWARE` in `settings.py`:
143
258
 
@@ -148,7 +263,7 @@ MIDDLEWARE = [
148
263
  ]
149
264
  ```
150
265
 
151
- #### Behavior
266
+ #### Response Time Middleware Behavior
152
267
 
153
268
  - Measures the time taken to process each request.
154
269
  - Adds a header `X-Response-Time` to each HTTP response.
@@ -166,7 +281,7 @@ X-Response-Time: 0.01234 seconds
166
281
  INFO: Request processed in 0.01234 seconds
167
282
  ```
168
283
 
169
- ### 4. Throttle Utilities
284
+ ### 6. Throttle Utilities
170
285
 
171
286
  #### `ThrottleInfoJSONRenderer`
172
287
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: djresttoolkit
3
- Version: 0.6.1
3
+ Version: 0.7.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
@@ -84,9 +84,124 @@ 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. EmailSender
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
+ Here’s a **concise API reference** for your database flush management command for `djresttoolkit`:
145
+
146
+ ---
147
+
148
+ ### 2. DB Flush Command
149
+
150
+ ```python
151
+ from djresttoolkit.management.commands import flush
152
+ ```
153
+
154
+ #### `manage.py dbflush`
155
+
156
+ Command to **delete all records** from the database for all models or a specific model and **reset auto-increment IDs**.
157
+
158
+ #### Usage
159
+
160
+ ```bash
161
+ python manage.py flush [--model ModelName] [--yes]
162
+ ```
163
+
164
+ #### dbflush command options
165
+
166
+ - `--model`: Name of the model to flush (case-sensitive, e.g., `User`). If omitted, flushes all models.
167
+ - `--yes`: Skip confirmation prompt. Without this, the command asks for confirmation before deleting.
168
+
169
+ #### dbflush command behavior
170
+
171
+ - Deletes all records for the specified model or all models.
172
+ - Resets primary key sequences for supported databases:
173
+
174
+ - PostgreSQL: `ALTER SEQUENCE ... RESTART WITH 1`
175
+ - SQLite: Deletes from `sqlite_sequence` table
176
+ - Others: Logs a warning (not implemented).
177
+ - Uses transactions to ensure safe operations.
178
+
179
+ #### dbflush command example
180
+
181
+ ```bash
182
+ # Flush all models with confirmation
183
+ python manage.py dbflush
184
+
185
+ # Flush a specific model (User) with confirmation
186
+ python manage.py dbflush --model User
187
+
188
+ # Flush all models without prompt
189
+ python manage.py dbflush --yes
190
+ ```
191
+
192
+ #### Output
193
+
194
+ ```bash
195
+ Flushed 10 records from model "User" and reset IDs.
196
+ ```
197
+
198
+ or
199
+
200
+ ```bash
201
+ Flushed 120 records from all models and reset IDs.
202
+ ```
203
+
204
+ ### 3. EmailSender
90
205
 
91
206
  ```python
92
207
  from djresttoolkit.mail import EmailSender, EmailContent, EmailTemplate
@@ -112,7 +227,7 @@ send(to: list[str], exceptions: bool = False) -> bool
112
227
  - `exceptions`: raise on error if `True`, else logs error
113
228
  - Returns `True` if sent, `False` on failure
114
229
 
115
- #### Example
230
+ #### Example for sending an email
116
231
 
117
232
  ```python
118
233
  content = EmailContent(
@@ -135,7 +250,7 @@ EmailSender(content).send(to=["user@example.com"])
135
250
 
136
251
  - `text`, `html` — template file paths
137
252
 
138
- ### 2. Custom DRF Exception Handler
253
+ ### 4. Custom DRF Exception Handler
139
254
 
140
255
  ```python
141
256
  from djresttoolkit.views import exception_handler
@@ -175,7 +290,7 @@ REST_FRAMEWORK = {
175
290
  - Tracks requests in cache and calculates `retry_after`.
176
291
  - Cleans expired timestamps automatically.
177
292
 
178
- ### 3. Response Time Middleware
293
+ ### 5. Response Time Middleware
179
294
 
180
295
  ```python
181
296
  from djresttoolkit.middlewares import ResponseTimeMiddleware
@@ -193,7 +308,7 @@ ResponseTimeMiddleware(get_response: Callable[[HttpRequest], HttpResponse])
193
308
 
194
309
  - `get_response`: The next middleware or view callable.
195
310
 
196
- #### Usage
311
+ #### Response Time Middleware Usage
197
312
 
198
313
  Add it to your Django `MIDDLEWARE` in `settings.py`:
199
314
 
@@ -204,7 +319,7 @@ MIDDLEWARE = [
204
319
  ]
205
320
  ```
206
321
 
207
- #### Behavior
322
+ #### Response Time Middleware Behavior
208
323
 
209
324
  - Measures the time taken to process each request.
210
325
  - Adds a header `X-Response-Time` to each HTTP response.
@@ -222,7 +337,7 @@ X-Response-Time: 0.01234 seconds
222
337
  INFO: Request processed in 0.01234 seconds
223
338
  ```
224
339
 
225
- ### 4. Throttle Utilities
340
+ ### 6. Throttle Utilities
226
341
 
227
342
  #### `ThrottleInfoJSONRenderer`
228
343
 
@@ -1,12 +1,13 @@
1
1
  LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
2
- README.md,sha256=mgYuT5MNL2ZmWzXLyU3VN0FA0sgyRM85Xn5EKxOM0Bs,5562
2
+ README.md,sha256=5bxE-TuyTrqyyWh3iISPe0GtLYyU7bOuCEdooPj_DQo,8418
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=B2WJqw2ncqf5nNhkM3XDFx13oNg2ccsULUQkFAjOyrY,105
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
12
13
  src/djresttoolkit/mail/__init__.py,sha256=tB9SdMlhfWQ640q4aobZ0H1c7fTWalpDL2I-onkr2VI,268
@@ -15,7 +16,8 @@ src/djresttoolkit/mail/_models.py,sha256=of5KsLGvsN2OWgDYgdtLEijulg817TXgsLKuUds
15
16
  src/djresttoolkit/mail/_types.py,sha256=zf6CcXR1ei_UmZ1nLAJa378OAJ6ftnBICqEOkzXPNw8,646
16
17
  src/djresttoolkit/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
18
  src/djresttoolkit/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- src/djresttoolkit/management/commands/dbseed.py,sha256=vS-s_B8No2rTl_T7HuIBg7f_Yp_6lztvK7FbcaxTZaA,4227
19
+ src/djresttoolkit/management/commands/dbflush.py,sha256=v7rXcuNQDiXLV7p0xzKMNXVeWAN7QKmq2qQQAbhHEEw,3423
20
+ src/djresttoolkit/management/commands/dbseed.py,sha256=sY87TvvzECG7aQXxsDjr45VzCzJpofLacBK49EYFK8M,4225
19
21
  src/djresttoolkit/middlewares/__init__.py,sha256=GZHU3Yy4xXoEi62tHn0UJNxN6XgGM2_HES8Bt5AS5Lk,100
20
22
  src/djresttoolkit/middlewares/_response_time_middleware.py,sha256=1wCwdkW5Ng6HJo8zx0F7ylms84OGP-1K0kbyG6Vacuk,908
21
23
  src/djresttoolkit/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -27,8 +29,8 @@ src/djresttoolkit/throttling/_throttle_inspector.py,sha256=Kss6ZxKy-EXq9UGaGprGD
27
29
  src/djresttoolkit/views/__init__.py,sha256=XrxBrs6sH4HmUzp41omcmy_y94pSaXAVn01ttQ022-4,76
28
30
  src/djresttoolkit/views/_exceptions/__init__.py,sha256=DrCUxuPNyBR4WhzNutn5HDxLa--q51ykIxSG7_bFsOI,83
29
31
  src/djresttoolkit/views/_exceptions/_exception_handler.py,sha256=_o7If47bzWLl57LeSXSWsIDsJGo2RIpwYAwNQ-hsHVY,2839
30
- djresttoolkit-0.6.1.dist-info/METADATA,sha256=doM3qba2_MGPAyrrfz3g79IjcNGaKyqiXYodOYFotso,8501
31
- djresttoolkit-0.6.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
32
- djresttoolkit-0.6.1.dist-info/entry_points.txt,sha256=YMhfTF-7mYppO8QqqWnvR_hyMWvoYxD6XI94_ViFu3k,60
33
- djresttoolkit-0.6.1.dist-info/licenses/LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
34
- djresttoolkit-0.6.1.dist-info/RECORD,,
32
+ djresttoolkit-0.7.0.dist-info/METADATA,sha256=k3gElJabHxN1l_dkMK0eld3Gt1W6QWofd2eyjT1-F_4,11357
33
+ djresttoolkit-0.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
34
+ djresttoolkit-0.7.0.dist-info/entry_points.txt,sha256=YMhfTF-7mYppO8QqqWnvR_hyMWvoYxD6XI94_ViFu3k,60
35
+ djresttoolkit-0.7.0.dist-info/licenses/LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
36
+ djresttoolkit-0.7.0.dist-info/RECORD,,
@@ -1,4 +1,10 @@
1
1
  from ._gen import Field, Gen
2
2
  from ._seed_model import SeedModel
3
+ from ._choice_field import choice_field
3
4
 
4
- __all__ = ["SeedModel", "Gen", "Field"]
5
+ __all__ = [
6
+ "SeedModel",
7
+ "Gen",
8
+ "Field",
9
+ "choice_field",
10
+ ]
@@ -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,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
+ )
@@ -74,7 +74,7 @@ class Command(BaseCommand):
74
74
  if (
75
75
  not model_name
76
76
  or model_name.lower()
77
- == attr.__name__.replace("DBSeedModel", "").lower()
77
+ == attr.__name__.replace("SeedModel", "").lower()
78
78
  ):
79
79
  seed_model_classes.append(attr)
80
80