djresttoolkit 0.10.0__py3-none-any.whl → 0.12.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 +148 -0
- {djresttoolkit-0.10.0.dist-info → djresttoolkit-0.12.0.dist-info}/METADATA +149 -1
- {djresttoolkit-0.10.0.dist-info → djresttoolkit-0.12.0.dist-info}/RECORD +11 -7
- src/djresttoolkit/models/mixins/__init__.py +11 -0
- src/djresttoolkit/models/mixins/_model_choice_fields_mixin.py +84 -0
- src/djresttoolkit/views/__init__.py +5 -1
- src/djresttoolkit/views/_api_views/__init__.py +0 -0
- src/djresttoolkit/views/_api_views/_choice_fields_apiview.py +42 -0
- {djresttoolkit-0.10.0.dist-info → djresttoolkit-0.12.0.dist-info}/WHEEL +0 -0
- {djresttoolkit-0.10.0.dist-info → djresttoolkit-0.12.0.dist-info}/entry_points.txt +0 -0
- {djresttoolkit-0.10.0.dist-info → djresttoolkit-0.12.0.dist-info}/licenses/LICENSE +0 -0
README.md
CHANGED
@@ -547,6 +547,154 @@ products = serializer.save()
|
|
547
547
|
- Automatically updates field error messages based on Django model definitions.
|
548
548
|
- Bulk creation is optimized using `model.objects.bulk_create()` for efficiency.
|
549
549
|
|
550
|
+
### 10. ModelChoiceFieldMixin — API Reference
|
551
|
+
|
552
|
+
```python
|
553
|
+
from djresttoolkit.models.mixins import ModelChoiceFieldMixin
|
554
|
+
```
|
555
|
+
|
556
|
+
### `ModelChoiceFieldMixin`
|
557
|
+
|
558
|
+
A **Django model mixin** to retrieve **choice fields** from a model, designed to work seamlessly with Django's `TextChoices`.
|
559
|
+
|
560
|
+
#### Class Attributes in Model Choice Field Mixin
|
561
|
+
|
562
|
+
- `model: type[Model] | None` — The Django model class to inspect. **Must be set.**
|
563
|
+
- `choice_fields: list[str] | None` — List of model field names that contain choices. **Must be set.**
|
564
|
+
|
565
|
+
#### Model Choice Field Mixin Methods
|
566
|
+
|
567
|
+
- `get_choices() -> dict[str, dict[str, str]]`
|
568
|
+
|
569
|
+
Retrieve the choice fields from the model as a dictionary.
|
570
|
+
|
571
|
+
- **Returns:**
|
572
|
+
|
573
|
+
```python
|
574
|
+
{
|
575
|
+
"field_name": {
|
576
|
+
"choice_value": "Choice Label",
|
577
|
+
...
|
578
|
+
},
|
579
|
+
...
|
580
|
+
}
|
581
|
+
```
|
582
|
+
|
583
|
+
- **Raises:**
|
584
|
+
|
585
|
+
- `AttributeDoesNotExist` — If `model` or `choice_fields` is not set.
|
586
|
+
- `ChoiceFieldNotFound` — If a field does not exist, has no choices, or has invalid choice format.
|
587
|
+
|
588
|
+
---
|
589
|
+
|
590
|
+
### Model Choice Field Mixin Example
|
591
|
+
|
592
|
+
```python
|
593
|
+
from django.db import models
|
594
|
+
from djresttoolkit.serializers.mixins import ModelChoiceFieldMixin
|
595
|
+
|
596
|
+
class Product(models.Model):
|
597
|
+
class Status(models.TextChoices):
|
598
|
+
DRAFT = "draft", "Draft"
|
599
|
+
PUBLISHED = "published", "Published"
|
600
|
+
|
601
|
+
status = models.CharField(max_length=20, choices=Status.choices)
|
602
|
+
category = models.CharField(max_length=50, choices=[
|
603
|
+
("a", "Category A"),
|
604
|
+
("b", "Category B"),
|
605
|
+
])
|
606
|
+
|
607
|
+
class ProductChoiceMixin(ModelChoiceFieldMixin):
|
608
|
+
model = Product
|
609
|
+
choice_fields = ["status", "category"]
|
610
|
+
|
611
|
+
choices = ProductChoiceMixin.get_choices()
|
612
|
+
print(choices)
|
613
|
+
# Output:
|
614
|
+
# {
|
615
|
+
# "status": {"draft": "Draft", "published": "Published"},
|
616
|
+
# "category": {"a": "Category A", "b": "Category B"}
|
617
|
+
# }
|
618
|
+
```
|
619
|
+
|
620
|
+
#### Features of Model Choice Field Mixin
|
621
|
+
|
622
|
+
- Safely validates that fields exist and have valid choices.
|
623
|
+
- Returns a ready-to-use dictionary mapping values to labels.
|
624
|
+
- Ideal for DRF serializers, forms, and admin customization.
|
625
|
+
|
626
|
+
Here’s a concise **docs entry** for your `ChoiceFieldsAPIView` suitable for `djresttoolkit` documentation:
|
627
|
+
|
628
|
+
---
|
629
|
+
|
630
|
+
### 11. ChoiceFieldsAPIView — API Reference
|
631
|
+
|
632
|
+
```python
|
633
|
+
from djresttoolkit.views import ChoiceFieldsAPIView
|
634
|
+
```
|
635
|
+
|
636
|
+
#### `ChoiceFieldsAPIView`
|
637
|
+
|
638
|
+
A **generic DRF API view** to return all choices for specified model fields.
|
639
|
+
|
640
|
+
#### Class Attributes of Choice Fields APIView
|
641
|
+
|
642
|
+
- `model_class: type[Model] | None` — The Django model to inspect. **Must be set.**
|
643
|
+
- `choice_fields: list[str] | None` — List of fields on the model with choices. **Must be set.**
|
644
|
+
|
645
|
+
---
|
646
|
+
|
647
|
+
#### Choice Fields APIView Methods
|
648
|
+
|
649
|
+
- `get(request: Request) -> Response`
|
650
|
+
|
651
|
+
Fetches the choices for the configured model fields.
|
652
|
+
|
653
|
+
- **Returns:**
|
654
|
+
- `200 OK` — JSON object containing all choices:
|
655
|
+
|
656
|
+
```json
|
657
|
+
{
|
658
|
+
"choices": {
|
659
|
+
"status": {"draft": "Draft", "published": "Published"},
|
660
|
+
"category": {"a": "Category A", "b": "Category B"}
|
661
|
+
}
|
662
|
+
}
|
663
|
+
```
|
664
|
+
|
665
|
+
- `400 Bad Request` — If any error occurs while retrieving choices.
|
666
|
+
|
667
|
+
- **Raises:**
|
668
|
+
- `AttributeDoesNotExist` — If `model_class` or `choice_fields` is not set.
|
669
|
+
|
670
|
+
---
|
671
|
+
|
672
|
+
### Example of Choice Fields APIView
|
673
|
+
|
674
|
+
```python
|
675
|
+
from django.urls import path
|
676
|
+
from djresttoolkit.views import ChoiceFieldsAPIView
|
677
|
+
from myapp.models import Product
|
678
|
+
|
679
|
+
class ProductChoiceAPI(ChoiceFieldsAPIView):
|
680
|
+
model_class = Product
|
681
|
+
choice_fields = ["status", "category"]
|
682
|
+
|
683
|
+
urlpatterns = [
|
684
|
+
path(
|
685
|
+
"api/v1/product-choices/",
|
686
|
+
ProductChoiceAPI.as_view(),
|
687
|
+
name="product-choices"
|
688
|
+
),
|
689
|
+
]
|
690
|
+
```
|
691
|
+
|
692
|
+
#### Choice Fields APIView Features
|
693
|
+
|
694
|
+
- Dynamically returns all choices for selected fields in a model.
|
695
|
+
- Useful for frontend forms or API consumers that need selectable options.
|
696
|
+
- Integrates seamlessly with `ModelChoiceFieldMixin` from `djresttoolkit`.
|
697
|
+
|
550
698
|
## 🛠️ Planned Features
|
551
699
|
|
552
700
|
- Add more utils
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: djresttoolkit
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.12.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
|
@@ -605,6 +605,154 @@ products = serializer.save()
|
|
605
605
|
- Automatically updates field error messages based on Django model definitions.
|
606
606
|
- Bulk creation is optimized using `model.objects.bulk_create()` for efficiency.
|
607
607
|
|
608
|
+
### 10. ModelChoiceFieldMixin — API Reference
|
609
|
+
|
610
|
+
```python
|
611
|
+
from djresttoolkit.models.mixins import ModelChoiceFieldMixin
|
612
|
+
```
|
613
|
+
|
614
|
+
### `ModelChoiceFieldMixin`
|
615
|
+
|
616
|
+
A **Django model mixin** to retrieve **choice fields** from a model, designed to work seamlessly with Django's `TextChoices`.
|
617
|
+
|
618
|
+
#### Class Attributes in Model Choice Field Mixin
|
619
|
+
|
620
|
+
- `model: type[Model] | None` — The Django model class to inspect. **Must be set.**
|
621
|
+
- `choice_fields: list[str] | None` — List of model field names that contain choices. **Must be set.**
|
622
|
+
|
623
|
+
#### Model Choice Field Mixin Methods
|
624
|
+
|
625
|
+
- `get_choices() -> dict[str, dict[str, str]]`
|
626
|
+
|
627
|
+
Retrieve the choice fields from the model as a dictionary.
|
628
|
+
|
629
|
+
- **Returns:**
|
630
|
+
|
631
|
+
```python
|
632
|
+
{
|
633
|
+
"field_name": {
|
634
|
+
"choice_value": "Choice Label",
|
635
|
+
...
|
636
|
+
},
|
637
|
+
...
|
638
|
+
}
|
639
|
+
```
|
640
|
+
|
641
|
+
- **Raises:**
|
642
|
+
|
643
|
+
- `AttributeDoesNotExist` — If `model` or `choice_fields` is not set.
|
644
|
+
- `ChoiceFieldNotFound` — If a field does not exist, has no choices, or has invalid choice format.
|
645
|
+
|
646
|
+
---
|
647
|
+
|
648
|
+
### Model Choice Field Mixin Example
|
649
|
+
|
650
|
+
```python
|
651
|
+
from django.db import models
|
652
|
+
from djresttoolkit.serializers.mixins import ModelChoiceFieldMixin
|
653
|
+
|
654
|
+
class Product(models.Model):
|
655
|
+
class Status(models.TextChoices):
|
656
|
+
DRAFT = "draft", "Draft"
|
657
|
+
PUBLISHED = "published", "Published"
|
658
|
+
|
659
|
+
status = models.CharField(max_length=20, choices=Status.choices)
|
660
|
+
category = models.CharField(max_length=50, choices=[
|
661
|
+
("a", "Category A"),
|
662
|
+
("b", "Category B"),
|
663
|
+
])
|
664
|
+
|
665
|
+
class ProductChoiceMixin(ModelChoiceFieldMixin):
|
666
|
+
model = Product
|
667
|
+
choice_fields = ["status", "category"]
|
668
|
+
|
669
|
+
choices = ProductChoiceMixin.get_choices()
|
670
|
+
print(choices)
|
671
|
+
# Output:
|
672
|
+
# {
|
673
|
+
# "status": {"draft": "Draft", "published": "Published"},
|
674
|
+
# "category": {"a": "Category A", "b": "Category B"}
|
675
|
+
# }
|
676
|
+
```
|
677
|
+
|
678
|
+
#### Features of Model Choice Field Mixin
|
679
|
+
|
680
|
+
- Safely validates that fields exist and have valid choices.
|
681
|
+
- Returns a ready-to-use dictionary mapping values to labels.
|
682
|
+
- Ideal for DRF serializers, forms, and admin customization.
|
683
|
+
|
684
|
+
Here’s a concise **docs entry** for your `ChoiceFieldsAPIView` suitable for `djresttoolkit` documentation:
|
685
|
+
|
686
|
+
---
|
687
|
+
|
688
|
+
### 11. ChoiceFieldsAPIView — API Reference
|
689
|
+
|
690
|
+
```python
|
691
|
+
from djresttoolkit.views import ChoiceFieldsAPIView
|
692
|
+
```
|
693
|
+
|
694
|
+
#### `ChoiceFieldsAPIView`
|
695
|
+
|
696
|
+
A **generic DRF API view** to return all choices for specified model fields.
|
697
|
+
|
698
|
+
#### Class Attributes of Choice Fields APIView
|
699
|
+
|
700
|
+
- `model_class: type[Model] | None` — The Django model to inspect. **Must be set.**
|
701
|
+
- `choice_fields: list[str] | None` — List of fields on the model with choices. **Must be set.**
|
702
|
+
|
703
|
+
---
|
704
|
+
|
705
|
+
#### Choice Fields APIView Methods
|
706
|
+
|
707
|
+
- `get(request: Request) -> Response`
|
708
|
+
|
709
|
+
Fetches the choices for the configured model fields.
|
710
|
+
|
711
|
+
- **Returns:**
|
712
|
+
- `200 OK` — JSON object containing all choices:
|
713
|
+
|
714
|
+
```json
|
715
|
+
{
|
716
|
+
"choices": {
|
717
|
+
"status": {"draft": "Draft", "published": "Published"},
|
718
|
+
"category": {"a": "Category A", "b": "Category B"}
|
719
|
+
}
|
720
|
+
}
|
721
|
+
```
|
722
|
+
|
723
|
+
- `400 Bad Request` — If any error occurs while retrieving choices.
|
724
|
+
|
725
|
+
- **Raises:**
|
726
|
+
- `AttributeDoesNotExist` — If `model_class` or `choice_fields` is not set.
|
727
|
+
|
728
|
+
---
|
729
|
+
|
730
|
+
### Example of Choice Fields APIView
|
731
|
+
|
732
|
+
```python
|
733
|
+
from django.urls import path
|
734
|
+
from djresttoolkit.views import ChoiceFieldsAPIView
|
735
|
+
from myapp.models import Product
|
736
|
+
|
737
|
+
class ProductChoiceAPI(ChoiceFieldsAPIView):
|
738
|
+
model_class = Product
|
739
|
+
choice_fields = ["status", "category"]
|
740
|
+
|
741
|
+
urlpatterns = [
|
742
|
+
path(
|
743
|
+
"api/v1/product-choices/",
|
744
|
+
ProductChoiceAPI.as_view(),
|
745
|
+
name="product-choices"
|
746
|
+
),
|
747
|
+
]
|
748
|
+
```
|
749
|
+
|
750
|
+
#### Choice Fields APIView Features
|
751
|
+
|
752
|
+
- Dynamically returns all choices for selected fields in a model.
|
753
|
+
- Useful for frontend forms or API consumers that need selectable options.
|
754
|
+
- Integrates seamlessly with `ModelChoiceFieldMixin` from `djresttoolkit`.
|
755
|
+
|
608
756
|
## 🛠️ Planned Features
|
609
757
|
|
610
758
|
- Add more utils
|
@@ -1,5 +1,5 @@
|
|
1
1
|
LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
|
2
|
-
README.md,sha256=
|
2
|
+
README.md,sha256=swcg_Yd0tKwp4PDXQn7gfj7HKpwLs-UPV4jvqOHvHvQ,18485
|
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
|
@@ -24,6 +24,8 @@ src/djresttoolkit/middlewares/__init__.py,sha256=GZHU3Yy4xXoEi62tHn0UJNxN6XgGM2_
|
|
24
24
|
src/djresttoolkit/middlewares/_response_time_middleware.py,sha256=1wCwdkW5Ng6HJo8zx0F7ylms84OGP-1K0kbyG6Vacuk,908
|
25
25
|
src/djresttoolkit/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
26
|
src/djresttoolkit/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
|
+
src/djresttoolkit/models/mixins/__init__.py,sha256=MHwv36f3nHwI0bXeejuO7MTYuV93ln2tSyCCipS2xVw,223
|
28
|
+
src/djresttoolkit/models/mixins/_model_choice_fields_mixin.py,sha256=9FZbe3PwrtIUZYGQh1gcOix5bfeyvKEOaNmkemvZX8E,2843
|
27
29
|
src/djresttoolkit/renderers/__init__.py,sha256=kmFMPRiMfD8CuJTN1_-6Z_Hqil3x8GBM0IN1roZESm0,107
|
28
30
|
src/djresttoolkit/renderers/_throttle_info_json_renderer.py,sha256=aP2cN4cB_Imcpy732zsPBQrMQqcKEs5R3dld5Y_4AMU,1089
|
29
31
|
src/djresttoolkit/serializers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -32,11 +34,13 @@ src/djresttoolkit/serializers/mixins/_absolute_url_file_mixin.py,sha256=5ewael0_
|
|
32
34
|
src/djresttoolkit/serializers/mixins/_bulk_create_mixin.py,sha256=9ZWm2MNaZOhmhKlWOu6VECtlDbUtaPeceGHmivDYwYQ,3248
|
33
35
|
src/djresttoolkit/throttling/__init__.py,sha256=01sjMymjx8XjqnAw3bEBLc-JtfhCDrp5dGxSNXMvPpU,84
|
34
36
|
src/djresttoolkit/throttling/_throttle_inspector.py,sha256=Kss6ZxKy-EXq9UGaGprGDhpSuJ5992bmEYZSWmUVBHo,6480
|
35
|
-
src/djresttoolkit/views/__init__.py,sha256=
|
37
|
+
src/djresttoolkit/views/__init__.py,sha256=QuJ9C0Vfzkfrwyqzunxh-A-aErmS6yOoy0uzjDu3oG8,177
|
38
|
+
src/djresttoolkit/views/_api_views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
|
+
src/djresttoolkit/views/_api_views/_choice_fields_apiview.py,sha256=zABPgqxMVaWd814B_sC64bWL61fDJkyYQZmJXQCa6Xc,1395
|
36
40
|
src/djresttoolkit/views/_exceptions/__init__.py,sha256=DrCUxuPNyBR4WhzNutn5HDxLa--q51ykIxSG7_bFsOI,83
|
37
41
|
src/djresttoolkit/views/_exceptions/_exception_handler.py,sha256=_o7If47bzWLl57LeSXSWsIDsJGo2RIpwYAwNQ-hsHVY,2839
|
38
|
-
djresttoolkit-0.
|
39
|
-
djresttoolkit-0.
|
40
|
-
djresttoolkit-0.
|
41
|
-
djresttoolkit-0.
|
42
|
-
djresttoolkit-0.
|
42
|
+
djresttoolkit-0.12.0.dist-info/METADATA,sha256=QP01vFRs3pOUXn7AuZ4kCVC37ZVo06HgiFm48wdaWVE,21495
|
43
|
+
djresttoolkit-0.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
44
|
+
djresttoolkit-0.12.0.dist-info/entry_points.txt,sha256=YMhfTF-7mYppO8QqqWnvR_hyMWvoYxD6XI94_ViFu3k,60
|
45
|
+
djresttoolkit-0.12.0.dist-info/licenses/LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
|
46
|
+
djresttoolkit-0.12.0.dist-info/RECORD,,
|
@@ -0,0 +1,84 @@
|
|
1
|
+
from typing import Iterable, Tuple, cast
|
2
|
+
|
3
|
+
from django.db.models import Model
|
4
|
+
from django.core.exceptions import FieldDoesNotExist
|
5
|
+
|
6
|
+
|
7
|
+
class AttributeDoesNotExist(Exception):
|
8
|
+
"""
|
9
|
+
Exception raised when a required attribute is missing in the class.
|
10
|
+
"""
|
11
|
+
|
12
|
+
|
13
|
+
class ChoiceFieldNotFound(Exception):
|
14
|
+
"""
|
15
|
+
Exception raised when a specified choice field is missing
|
16
|
+
or has invalid/empty choices in the model.
|
17
|
+
"""
|
18
|
+
|
19
|
+
|
20
|
+
class ModelChoiceFieldMixin:
|
21
|
+
"""
|
22
|
+
Mixin to retrieve choice fields from a Django model.
|
23
|
+
Designed to work seamlessly with Django's TextChoices.
|
24
|
+
"""
|
25
|
+
|
26
|
+
model: type[Model] | None = None
|
27
|
+
choice_fields: list[str] | None = None
|
28
|
+
|
29
|
+
@classmethod
|
30
|
+
def get_choices(cls) -> dict[str, dict[str, str]]:
|
31
|
+
"""
|
32
|
+
Retrieve the choice fields from the model class.
|
33
|
+
|
34
|
+
Returns:
|
35
|
+
dict[str, dict[str, str]]: A dictionary where keys are field names
|
36
|
+
and values are dictionaries of choices (value => label).
|
37
|
+
|
38
|
+
Raises:
|
39
|
+
ModelAttributeNotFound: If the model attribute is not set.
|
40
|
+
ChoiceFieldAttributeNotFound: If the choice_fields attribute is not set.
|
41
|
+
ChoiceFieldNotFound: If a field does not exist, has no choices,
|
42
|
+
or has an invalid choice format.
|
43
|
+
"""
|
44
|
+
|
45
|
+
if cls.model is None:
|
46
|
+
raise AttributeDoesNotExist("Model attribute is not set in the class.")
|
47
|
+
|
48
|
+
if cls.choice_fields is None:
|
49
|
+
raise AttributeDoesNotExist(
|
50
|
+
"The choice_fields attribute must be set in the class."
|
51
|
+
)
|
52
|
+
|
53
|
+
choices_as_dict: dict[str, dict[str, str]] = {}
|
54
|
+
|
55
|
+
for field in cls.choice_fields:
|
56
|
+
try:
|
57
|
+
field_obj = cls.model._meta.get_field(field) # type: ignore[attr-defined]
|
58
|
+
except FieldDoesNotExist as e:
|
59
|
+
raise ChoiceFieldNotFound(
|
60
|
+
f"The field '{field}' does not exist in model '{cls.model.__name__}'."
|
61
|
+
) from e
|
62
|
+
|
63
|
+
raw_choices = cast(
|
64
|
+
Iterable[Tuple[str, str]],
|
65
|
+
field_obj.choices or [], # type: ignore[union-attr]
|
66
|
+
)
|
67
|
+
|
68
|
+
if not raw_choices:
|
69
|
+
raise ChoiceFieldNotFound(
|
70
|
+
f"The field '{field}' in model '{cls.model.__name__}' has no choices defined."
|
71
|
+
)
|
72
|
+
|
73
|
+
if not all(
|
74
|
+
isinstance(choice, (list, tuple)) and len(choice) == 2 # type: ignore[misc]
|
75
|
+
for choice in raw_choices
|
76
|
+
):
|
77
|
+
raise ChoiceFieldNotFound(
|
78
|
+
f"The field '{field}' in model '{cls.model.__name__}' has invalid choice format. "
|
79
|
+
"Expected an iterable of 2-tuples (value, label)."
|
80
|
+
)
|
81
|
+
|
82
|
+
choices_as_dict[field] = dict(raw_choices)
|
83
|
+
|
84
|
+
return choices_as_dict
|
File without changes
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# views.py
|
2
|
+
from rest_framework.views import APIView
|
3
|
+
from rest_framework.response import Response
|
4
|
+
from rest_framework.request import Request
|
5
|
+
from rest_framework import status
|
6
|
+
from djresttoolkit.models.mixins import ModelChoiceFieldMixin, AttributeDoesNotExist
|
7
|
+
from django.db.models import Model
|
8
|
+
|
9
|
+
|
10
|
+
class ChoiceFieldsAPIView(APIView):
|
11
|
+
"""
|
12
|
+
Generic API view to return choice fields from a model.
|
13
|
+
"""
|
14
|
+
|
15
|
+
model_class: type[Model] | None = None
|
16
|
+
choice_fields: list[str] | None = None
|
17
|
+
|
18
|
+
def get(self, request: Request) -> Response:
|
19
|
+
"""
|
20
|
+
Return a JSON response with all choices for the specified fields.
|
21
|
+
"""
|
22
|
+
if not self.model_class or not self.choice_fields:
|
23
|
+
raise AttributeDoesNotExist(
|
24
|
+
"model_class and choice_fields must be set.",
|
25
|
+
)
|
26
|
+
|
27
|
+
# Dynamically create a mixin instance
|
28
|
+
class DynamicChoiceMixin(ModelChoiceFieldMixin):
|
29
|
+
model = self.model_class
|
30
|
+
choice_fields = self.choice_fields
|
31
|
+
|
32
|
+
try:
|
33
|
+
choices = DynamicChoiceMixin.get_choices()
|
34
|
+
return Response(
|
35
|
+
{"choices": choices},
|
36
|
+
status=status.HTTP_200_OK,
|
37
|
+
)
|
38
|
+
except Exception:
|
39
|
+
return Response(
|
40
|
+
{"detail": "An error occurred while retrieving choices."},
|
41
|
+
status=status.HTTP_400_BAD_REQUEST,
|
42
|
+
)
|
File without changes
|
File without changes
|
File without changes
|