turbodrf 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.
Files changed (53) hide show
  1. turbodrf-0.1.0/API.md +472 -0
  2. turbodrf-0.1.0/CONTRIBUTING.md +409 -0
  3. turbodrf-0.1.0/DEPLOYMENT.md +218 -0
  4. turbodrf-0.1.0/INSTALL.md +280 -0
  5. turbodrf-0.1.0/LICENSE +21 -0
  6. turbodrf-0.1.0/MANIFEST.in +27 -0
  7. turbodrf-0.1.0/PKG-INFO +1569 -0
  8. turbodrf-0.1.0/README.md +1519 -0
  9. turbodrf-0.1.0/pyproject.toml +100 -0
  10. turbodrf-0.1.0/setup.cfg +4 -0
  11. turbodrf-0.1.0/setup.py +58 -0
  12. turbodrf-0.1.0/tests/__init__.py +7 -0
  13. turbodrf-0.1.0/tests/fixtures.py +207 -0
  14. turbodrf-0.1.0/tests/integration/__init__.py +0 -0
  15. turbodrf-0.1.0/tests/integration/test_api_endpoints.py +329 -0
  16. turbodrf-0.1.0/tests/integration/test_role_permissions.py +320 -0
  17. turbodrf-0.1.0/tests/settings.py +186 -0
  18. turbodrf-0.1.0/tests/test_app/__init__.py +0 -0
  19. turbodrf-0.1.0/tests/test_app/apps.py +26 -0
  20. turbodrf-0.1.0/tests/test_app/models.py +108 -0
  21. turbodrf-0.1.0/tests/test_package.py +71 -0
  22. turbodrf-0.1.0/tests/test_runner.py +31 -0
  23. turbodrf-0.1.0/tests/unit/__init__.py +0 -0
  24. turbodrf-0.1.0/tests/unit/test_custom_viewsets.py +296 -0
  25. turbodrf-0.1.0/tests/unit/test_default_permissions.py +148 -0
  26. turbodrf-0.1.0/tests/unit/test_mixins.py +118 -0
  27. turbodrf-0.1.0/tests/unit/test_permissions.py +173 -0
  28. turbodrf-0.1.0/tests/unit/test_router.py +129 -0
  29. turbodrf-0.1.0/tests/unit/test_serializers.py +261 -0
  30. turbodrf-0.1.0/tests/unit/test_views.py +218 -0
  31. turbodrf-0.1.0/tests/urls.py +24 -0
  32. turbodrf-0.1.0/tox.ini +31 -0
  33. turbodrf-0.1.0/turbodrf/__init__.py +55 -0
  34. turbodrf-0.1.0/turbodrf/apps.py +15 -0
  35. turbodrf-0.1.0/turbodrf/documentation.py +94 -0
  36. turbodrf-0.1.0/turbodrf/filters.py +64 -0
  37. turbodrf-0.1.0/turbodrf/metadata.py +110 -0
  38. turbodrf-0.1.0/turbodrf/mixins.py +160 -0
  39. turbodrf-0.1.0/turbodrf/permissions.py +181 -0
  40. turbodrf-0.1.0/turbodrf/router.py +101 -0
  41. turbodrf-0.1.0/turbodrf/serializers.py +511 -0
  42. turbodrf-0.1.0/turbodrf/settings.py +26 -0
  43. turbodrf-0.1.0/turbodrf/swagger.py +269 -0
  44. turbodrf-0.1.0/turbodrf/swagger_ui.py +6 -0
  45. turbodrf-0.1.0/turbodrf/urls.py +29 -0
  46. turbodrf-0.1.0/turbodrf/user_extensions.py +51 -0
  47. turbodrf-0.1.0/turbodrf/utils.py +65 -0
  48. turbodrf-0.1.0/turbodrf/views.py +455 -0
  49. turbodrf-0.1.0/turbodrf.egg-info/PKG-INFO +1569 -0
  50. turbodrf-0.1.0/turbodrf.egg-info/SOURCES.txt +51 -0
  51. turbodrf-0.1.0/turbodrf.egg-info/dependency_links.txt +1 -0
  52. turbodrf-0.1.0/turbodrf.egg-info/requires.txt +13 -0
  53. turbodrf-0.1.0/turbodrf.egg-info/top_level.txt +1 -0
turbodrf-0.1.0/API.md ADDED
@@ -0,0 +1,472 @@
1
+ # TurboDRF API Reference
2
+
3
+ This document provides a comprehensive API reference for TurboDRF.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Core Components](#core-components)
8
+ - [TurboDRFMixin](#turbodrfmixin)
9
+ - [TurboDRFRouter](#turbodrfrouter)
10
+ - [TurboDRFViewSet](#turbodrfviewset)
11
+ - [TurboDRFPermission](#turbodrfpermission)
12
+ - [TurboDRFSerializer](#turbodrfserializer)
13
+ - [Configuration](#configuration)
14
+ - [Model Configuration](#model-configuration)
15
+ - [Settings](#settings)
16
+ - [API Endpoints](#api-endpoints)
17
+ - [Query Parameters](#query-parameters)
18
+ - [Response Formats](#response-formats)
19
+ - [Error Handling](#error-handling)
20
+
21
+ ## Core Components
22
+
23
+ ### TurboDRFMixin
24
+
25
+ The core mixin that enables automatic API generation for Django models.
26
+
27
+ ```python
28
+ from turbodrf import TurboDRFMixin
29
+
30
+ class MyModel(models.Model, TurboDRFMixin):
31
+ # Model fields
32
+
33
+ @classmethod
34
+ def turbodrf(cls):
35
+ return {
36
+ 'fields': ['field1', 'field2'],
37
+ 'endpoint': 'custom-endpoint', # Optional
38
+ 'enabled': True # Optional
39
+ }
40
+ ```
41
+
42
+ #### Methods
43
+
44
+ ##### `turbodrf()`
45
+
46
+ **Type**: `@classmethod`
47
+
48
+ **Returns**: `dict`
49
+
50
+ Configuration method that defines how the model should be exposed in the API.
51
+
52
+ **Configuration Options**:
53
+
54
+ | Key | Type | Default | Description |
55
+ |-----|------|---------|-------------|
56
+ | `fields` | `list`, `dict`, or `str` | `'__all__'` | Fields to expose in API |
57
+ | `endpoint` | `str` | `'{model_name}s'` | Custom endpoint name |
58
+ | `enabled` | `bool` | `True` | Whether to enable API for this model |
59
+
60
+ **Field Configuration Examples**:
61
+
62
+ ```python
63
+ # Simple list (same fields for list and detail)
64
+ 'fields': ['title', 'author', 'price']
65
+
66
+ # Different fields for list vs detail
67
+ 'fields': {
68
+ 'list': ['title', 'author'],
69
+ 'detail': ['title', 'author', 'description', 'price']
70
+ }
71
+
72
+ # All fields
73
+ 'fields': '__all__'
74
+
75
+ # Nested fields
76
+ 'fields': ['title', 'author__name', 'category__parent__name']
77
+ ```
78
+
79
+ ##### `get_api_fields(view_type='list')`
80
+
81
+ **Type**: `@classmethod`
82
+
83
+ **Parameters**:
84
+ - `view_type` (str): Either 'list' or 'detail'
85
+
86
+ **Returns**: `list`
87
+
88
+ Get the fields for a specific view type based on the model's configuration.
89
+
90
+ ##### `get_field_type(field_path)`
91
+
92
+ **Type**: `@classmethod`
93
+
94
+ **Parameters**:
95
+ - `field_path` (str): Field path using double-underscore notation
96
+
97
+ **Returns**: `Field` or `None`
98
+
99
+ Resolve field type for nested fields.
100
+
101
+ ### TurboDRFRouter
102
+
103
+ Automatic router that discovers and registers all TurboDRF-enabled models.
104
+
105
+ ```python
106
+ from turbodrf import TurboDRFRouter
107
+
108
+ router = TurboDRFRouter()
109
+ # No manual registration needed!
110
+ ```
111
+
112
+ #### Methods
113
+
114
+ ##### `__init__(*args, **kwargs)`
115
+
116
+ Initialize the router and automatically discover all models.
117
+
118
+ **Parameters**: Same as DRF's `DefaultRouter`
119
+
120
+ ##### `discover_models()`
121
+
122
+ Automatically discover and register all models with TurboDRFMixin.
123
+
124
+ Called automatically during initialization.
125
+
126
+ ### TurboDRFViewSet
127
+
128
+ Base ViewSet class for all auto-generated APIs.
129
+
130
+ #### Features
131
+
132
+ - Automatic serializer generation
133
+ - Built-in pagination
134
+ - Search, filter, and ordering support
135
+ - Query optimization
136
+ - Permission handling
137
+
138
+ #### Properties
139
+
140
+ | Property | Type | Description |
141
+ |----------|------|-------------|
142
+ | `model` | `Model` | The Django model class |
143
+ | `permission_classes` | `list` | `[TurboDRFPermission]` |
144
+ | `pagination_class` | `class` | `TurboDRFPagination` |
145
+ | `filter_backends` | `list` | DjangoFilter, Search, Ordering |
146
+ | `search_fields` | `list` | From model's `searchable_fields` |
147
+ | `ordering_fields` | `str` | `'__all__'` |
148
+ | `filterset_fields` | `str` | `'__all__'` |
149
+
150
+ ### TurboDRFPermission
151
+
152
+ Role-based permission class.
153
+
154
+ #### Permission Format
155
+
156
+ ```
157
+ app_label.model_name.action
158
+ app_label.model_name.field_name.read
159
+ app_label.model_name.field_name.write
160
+ ```
161
+
162
+ #### Methods
163
+
164
+ ##### `has_permission(request, view)`
165
+
166
+ Check if user has permission to perform the requested action.
167
+
168
+ **Returns**: `bool`
169
+
170
+ ### TurboDRFSerializer
171
+
172
+ Base serializer with support for nested field notation.
173
+
174
+ #### Features
175
+
176
+ - Automatic handling of nested fields
177
+ - Dynamic field inclusion based on configuration
178
+ - Support for `field__subfield` notation
179
+
180
+ ## Configuration
181
+
182
+ ### Model Configuration
183
+
184
+ #### Basic Example
185
+
186
+ ```python
187
+ class Book(models.Model, TurboDRFMixin):
188
+ title = models.CharField(max_length=200)
189
+ author = models.ForeignKey(Author, on_delete=models.CASCADE)
190
+ price = models.DecimalField(max_digits=10, decimal_places=2)
191
+
192
+ # Enable search
193
+ searchable_fields = ['title', 'author__name']
194
+
195
+ @classmethod
196
+ def turbodrf(cls):
197
+ return {
198
+ 'fields': ['title', 'author__name', 'price']
199
+ }
200
+ ```
201
+
202
+ #### Advanced Example
203
+
204
+ ```python
205
+ class Product(models.Model, TurboDRFMixin):
206
+ name = models.CharField(max_length=200)
207
+ description = models.TextField()
208
+ category = models.ForeignKey(Category, on_delete=models.CASCADE)
209
+ price = models.DecimalField(max_digits=10, decimal_places=2)
210
+
211
+ searchable_fields = ['name', 'description']
212
+
213
+ @classmethod
214
+ def turbodrf(cls):
215
+ return {
216
+ 'endpoint': 'products', # Custom endpoint
217
+ 'fields': {
218
+ 'list': ['name', 'category__name', 'price'],
219
+ 'detail': [
220
+ 'name', 'description', 'price',
221
+ 'category__name', 'category__description'
222
+ ]
223
+ }
224
+ }
225
+ ```
226
+
227
+ ### Settings
228
+
229
+ Add to your Django settings:
230
+
231
+ ```python
232
+ # Required apps
233
+ INSTALLED_APPS = [
234
+ # ...
235
+ 'rest_framework',
236
+ 'django_filters',
237
+ 'drf_yasg',
238
+ 'turbodrf',
239
+ ]
240
+
241
+ # Role-based permissions
242
+ TURBODRF_ROLES = {
243
+ 'admin': [
244
+ # Model permissions
245
+ 'app.model.read',
246
+ 'app.model.create',
247
+ 'app.model.update',
248
+ 'app.model.delete',
249
+ # Field permissions
250
+ 'app.model.field.read',
251
+ 'app.model.field.write',
252
+ ],
253
+ 'editor': [
254
+ 'app.model.read',
255
+ 'app.model.update',
256
+ 'app.model.field.read',
257
+ ],
258
+ 'viewer': [
259
+ 'app.model.read',
260
+ ]
261
+ }
262
+ ```
263
+
264
+ ## API Endpoints
265
+
266
+ For each model, TurboDRF generates:
267
+
268
+ | Method | Endpoint | Description |
269
+ |--------|----------|-------------|
270
+ | GET | `/api/{model}s/` | List all objects |
271
+ | POST | `/api/{model}s/` | Create new object |
272
+ | GET | `/api/{model}s/{id}/` | Retrieve specific object |
273
+ | PUT | `/api/{model}s/{id}/` | Update object (full) |
274
+ | PATCH | `/api/{model}s/{id}/` | Update object (partial) |
275
+ | DELETE | `/api/{model}s/{id}/` | Delete object |
276
+ | OPTIONS | `/api/{model}s/` | Get metadata |
277
+
278
+ ## Query Parameters
279
+
280
+ ### Pagination
281
+
282
+ | Parameter | Type | Default | Description |
283
+ |-----------|------|---------|-------------|
284
+ | `page` | int | 1 | Page number |
285
+ | `page_size` | int | 20 | Items per page (max 100) |
286
+
287
+ **Example**: `/api/books/?page=2&page_size=50`
288
+
289
+ ### Search
290
+
291
+ | Parameter | Type | Description |
292
+ |-----------|------|-------------|
293
+ | `search` | string | Search across `searchable_fields` |
294
+
295
+ **Example**: `/api/books/?search=django`
296
+
297
+ ### Filtering
298
+
299
+ Use Django's field lookups:
300
+
301
+ ```
302
+ /api/books/?price__gte=10&price__lte=50
303
+ /api/books/?author__name__icontains=smith
304
+ /api/books/?published_date__year=2023
305
+ /api/books/?is_active=true
306
+ ```
307
+
308
+ ### Ordering
309
+
310
+ | Parameter | Type | Description |
311
+ |-----------|------|-------------|
312
+ | `ordering` | string | Field(s) to order by |
313
+
314
+ **Examples**:
315
+ - `/api/books/?ordering=price` (ascending)
316
+ - `/api/books/?ordering=-price` (descending)
317
+ - `/api/books/?ordering=-price,title` (multiple fields)
318
+
319
+ ## Response Formats
320
+
321
+ ### List Response
322
+
323
+ ```json
324
+ {
325
+ "pagination": {
326
+ "next": "http://example.com/api/books/?page=2",
327
+ "previous": null,
328
+ "current_page": 1,
329
+ "total_pages": 5,
330
+ "total_items": 100
331
+ },
332
+ "data": [
333
+ {
334
+ "id": 1,
335
+ "title": "Django for Beginners",
336
+ "author_name": "John Smith",
337
+ "price": "29.99"
338
+ }
339
+ // ... more items
340
+ ]
341
+ }
342
+ ```
343
+
344
+ ### Detail Response
345
+
346
+ ```json
347
+ {
348
+ "id": 1,
349
+ "title": "Django for Beginners",
350
+ "description": "Learn Django step by step",
351
+ "author_name": "John Smith",
352
+ "author_email": "john@example.com",
353
+ "price": "29.99",
354
+ "created_at": "2024-01-01T00:00:00Z"
355
+ }
356
+ ```
357
+
358
+ ### Error Response
359
+
360
+ ```json
361
+ {
362
+ "detail": "Not found."
363
+ }
364
+ ```
365
+
366
+ ```json
367
+ {
368
+ "field_name": [
369
+ "This field is required."
370
+ ]
371
+ }
372
+ ```
373
+
374
+ ## Error Handling
375
+
376
+ ### HTTP Status Codes
377
+
378
+ | Code | Description | When Used |
379
+ |------|-------------|-----------|
380
+ | 200 | OK | Successful GET, PUT, PATCH |
381
+ | 201 | Created | Successful POST |
382
+ | 204 | No Content | Successful DELETE |
383
+ | 400 | Bad Request | Invalid data |
384
+ | 401 | Unauthorized | No authentication |
385
+ | 403 | Forbidden | No permission |
386
+ | 404 | Not Found | Object doesn't exist |
387
+ | 405 | Method Not Allowed | Invalid HTTP method |
388
+ | 500 | Server Error | Internal error |
389
+
390
+ ### Common Errors
391
+
392
+ #### Permission Denied
393
+
394
+ ```json
395
+ {
396
+ "detail": "You do not have permission to perform this action."
397
+ }
398
+ ```
399
+
400
+ **Solution**: Check user roles and permissions in `TURBODRF_ROLES`.
401
+
402
+ #### Field Not Found
403
+
404
+ ```json
405
+ {
406
+ "detail": "Field 'invalid_field' does not exist on model 'Book'."
407
+ }
408
+ ```
409
+
410
+ **Solution**: Check field names in model's `turbodrf()` configuration.
411
+
412
+ #### Invalid Filter
413
+
414
+ ```json
415
+ {
416
+ "detail": "Invalid filter: 'invalid_lookup'."
417
+ }
418
+ ```
419
+
420
+ **Solution**: Use valid Django field lookups.
421
+
422
+ ## Advanced Usage
423
+
424
+ ### Custom ViewSet Methods
425
+
426
+ ```python
427
+ from turbodrf import TurboDRFViewSet
428
+ from rest_framework.decorators import action
429
+ from rest_framework.response import Response
430
+
431
+ class CustomBookViewSet(TurboDRFViewSet):
432
+ model = Book
433
+
434
+ @action(detail=True, methods=['post'])
435
+ def set_favorite(self, request, pk=None):
436
+ book = self.get_object()
437
+ # Custom logic
438
+ return Response({'status': 'favorite set'})
439
+ ```
440
+
441
+ ### Extending Serializers
442
+
443
+ ```python
444
+ from turbodrf import TurboDRFSerializer
445
+
446
+ class CustomBookSerializer(TurboDRFSerializer):
447
+ # Add custom fields or methods
448
+
449
+ class Meta:
450
+ model = Book
451
+ fields = ['title', 'author', 'custom_field']
452
+ ```
453
+
454
+ ### Performance Optimization
455
+
456
+ TurboDRF automatically optimizes queries, but you can enhance it:
457
+
458
+ ```python
459
+ class Book(models.Model, TurboDRFMixin):
460
+ # Model fields
461
+
462
+ @classmethod
463
+ def turbodrf(cls):
464
+ return {
465
+ 'fields': {
466
+ 'list': ['title', 'author__name'], # Minimal fields
467
+ 'detail': '__all__' # All fields in detail
468
+ }
469
+ }
470
+ ```
471
+
472
+ This reduces data transfer in list views while providing complete information in detail views.