djresttoolkit 0.11.0__py3-none-any.whl → 0.13.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
@@ -564,7 +564,7 @@ A **Django model mixin** to retrieve **choice fields** from a model, designed to
564
564
 
565
565
  #### Model Choice Field Mixin Methods
566
566
 
567
- `get_choices() -> dict[str, dict[str, str]]`
567
+ - `get_choices() -> dict[str, dict[str, str]]`
568
568
 
569
569
  Retrieve the choice fields from the model as a dictionary.
570
570
 
@@ -623,6 +623,132 @@ print(choices)
623
623
  - Returns a ready-to-use dictionary mapping values to labels.
624
624
  - Ideal for DRF serializers, forms, and admin customization.
625
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
+
698
+ ### 12. RetrieveObjectMixin — API Reference
699
+
700
+ ```python
701
+ from djresttoolkit.views.mixins import RetrieveObjectMixin
702
+ ```
703
+
704
+ #### `RetrieveObjectMixin[T: Model]`
705
+
706
+ A **generic mixin** to retrieve a single Django model instance by filters.
707
+
708
+ #### Class Attributes of Retrieve Object Mixin
709
+
710
+ - `queryset: QuerySet[T] | None` — The queryset used to retrieve objects. **Must be set.**
711
+
712
+ #### Raises of Retrieve Object Mixin
713
+
714
+ - `QuerysetNotDefinedError` — If `queryset` is not set in the class.
715
+
716
+ #### Retrieve Object Mixin Methods
717
+
718
+ - `get_object(**filters: Any) -> T | None`
719
+
720
+ Retrieve a single model object using the provided filter criteria.
721
+
722
+ - **Parameters:**
723
+ - `**filters` — Keyword arguments to filter the queryset (e.g., `id=1`, `slug="abc"`).
724
+
725
+ - **Returns:**
726
+ - Model instance matching the filters, or `None` if no match is found.
727
+
728
+ #### Example of Retrieve Object Mixin
729
+
730
+ ```python
731
+ from rest_framework.views import APIView
732
+ from django.http import JsonResponse
733
+ from myapp.models import Book
734
+ from djresttoolkit.mixins import RetrieveObjectMixin
735
+
736
+ class BookDetailView(RetrieveObjectMixin[Book], APIView):
737
+ queryset = Book.objects.all()
738
+
739
+ def get(self, request, *args, **kwargs):
740
+ book = self.get_object(id=kwargs["id"])
741
+ if book:
742
+ return JsonResponse({"title": book.title, "author": book.author})
743
+ return JsonResponse({"detail": "Not found"}, status=404)
744
+ ```
745
+
746
+ #### Features of Retrieve Object Mixin
747
+
748
+ - Simplifies object retrieval in class-based views or DRF views.
749
+ - Returns `None` instead of raising `DoesNotExist`, making error handling easier.
750
+ - Works with any Django model and queryset.
751
+
626
752
  ## 🛠️ Planned Features
627
753
 
628
754
  - Add more utils
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: djresttoolkit
3
- Version: 0.11.0
3
+ Version: 0.13.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
@@ -622,7 +622,7 @@ A **Django model mixin** to retrieve **choice fields** from a model, designed to
622
622
 
623
623
  #### Model Choice Field Mixin Methods
624
624
 
625
- `get_choices() -> dict[str, dict[str, str]]`
625
+ - `get_choices() -> dict[str, dict[str, str]]`
626
626
 
627
627
  Retrieve the choice fields from the model as a dictionary.
628
628
 
@@ -681,6 +681,132 @@ print(choices)
681
681
  - Returns a ready-to-use dictionary mapping values to labels.
682
682
  - Ideal for DRF serializers, forms, and admin customization.
683
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
+
756
+ ### 12. RetrieveObjectMixin — API Reference
757
+
758
+ ```python
759
+ from djresttoolkit.views.mixins import RetrieveObjectMixin
760
+ ```
761
+
762
+ #### `RetrieveObjectMixin[T: Model]`
763
+
764
+ A **generic mixin** to retrieve a single Django model instance by filters.
765
+
766
+ #### Class Attributes of Retrieve Object Mixin
767
+
768
+ - `queryset: QuerySet[T] | None` — The queryset used to retrieve objects. **Must be set.**
769
+
770
+ #### Raises of Retrieve Object Mixin
771
+
772
+ - `QuerysetNotDefinedError` — If `queryset` is not set in the class.
773
+
774
+ #### Retrieve Object Mixin Methods
775
+
776
+ - `get_object(**filters: Any) -> T | None`
777
+
778
+ Retrieve a single model object using the provided filter criteria.
779
+
780
+ - **Parameters:**
781
+ - `**filters` — Keyword arguments to filter the queryset (e.g., `id=1`, `slug="abc"`).
782
+
783
+ - **Returns:**
784
+ - Model instance matching the filters, or `None` if no match is found.
785
+
786
+ #### Example of Retrieve Object Mixin
787
+
788
+ ```python
789
+ from rest_framework.views import APIView
790
+ from django.http import JsonResponse
791
+ from myapp.models import Book
792
+ from djresttoolkit.mixins import RetrieveObjectMixin
793
+
794
+ class BookDetailView(RetrieveObjectMixin[Book], APIView):
795
+ queryset = Book.objects.all()
796
+
797
+ def get(self, request, *args, **kwargs):
798
+ book = self.get_object(id=kwargs["id"])
799
+ if book:
800
+ return JsonResponse({"title": book.title, "author": book.author})
801
+ return JsonResponse({"detail": "Not found"}, status=404)
802
+ ```
803
+
804
+ #### Features of Retrieve Object Mixin
805
+
806
+ - Simplifies object retrieval in class-based views or DRF views.
807
+ - Returns `None` instead of raising `DoesNotExist`, making error handling easier.
808
+ - Works with any Django model and queryset.
809
+
684
810
  ## 🛠️ Planned Features
685
811
 
686
812
  - Add more utils
@@ -1,5 +1,5 @@
1
1
  LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
2
- README.md,sha256=WqoI3wWyhwdOz1IypIsKCoDFo06hg2xjE_1bTem-OBg,16675
2
+ README.md,sha256=GaxIplR2lXkKw0EPirrCMO6rLde0rdkv6Ch0W49a1B4,20113
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
@@ -34,11 +34,15 @@ src/djresttoolkit/serializers/mixins/_absolute_url_file_mixin.py,sha256=5ewael0_
34
34
  src/djresttoolkit/serializers/mixins/_bulk_create_mixin.py,sha256=9ZWm2MNaZOhmhKlWOu6VECtlDbUtaPeceGHmivDYwYQ,3248
35
35
  src/djresttoolkit/throttling/__init__.py,sha256=01sjMymjx8XjqnAw3bEBLc-JtfhCDrp5dGxSNXMvPpU,84
36
36
  src/djresttoolkit/throttling/_throttle_inspector.py,sha256=Kss6ZxKy-EXq9UGaGprGDhpSuJ5992bmEYZSWmUVBHo,6480
37
- src/djresttoolkit/views/__init__.py,sha256=XrxBrs6sH4HmUzp41omcmy_y94pSaXAVn01ttQ022-4,76
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
38
40
  src/djresttoolkit/views/_exceptions/__init__.py,sha256=DrCUxuPNyBR4WhzNutn5HDxLa--q51ykIxSG7_bFsOI,83
39
41
  src/djresttoolkit/views/_exceptions/_exception_handler.py,sha256=_o7If47bzWLl57LeSXSWsIDsJGo2RIpwYAwNQ-hsHVY,2839
40
- djresttoolkit-0.11.0.dist-info/METADATA,sha256=wcrkywl8zVg8D1XYLWqpTaSr5b3esYXMLXbC9tEzQU0,19685
41
- djresttoolkit-0.11.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
42
- djresttoolkit-0.11.0.dist-info/entry_points.txt,sha256=YMhfTF-7mYppO8QqqWnvR_hyMWvoYxD6XI94_ViFu3k,60
43
- djresttoolkit-0.11.0.dist-info/licenses/LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
44
- djresttoolkit-0.11.0.dist-info/RECORD,,
42
+ src/djresttoolkit/views/mixins/__init__.py,sha256=K-1tk5d8tCVViMynw5DdffJ3Oo5uHpEx32E3_4X2UxM,154
43
+ src/djresttoolkit/views/mixins/_retrieve_object_mixin.py,sha256=Q9znYPb07YXXUhsL7VIrk3BC-zDwjOhwLJKe2GPJ-k0,1155
44
+ djresttoolkit-0.13.0.dist-info/METADATA,sha256=iq6CfG1jgD-bHq6mREQaoixT451gcA4DIyoBSe6hRNg,23123
45
+ djresttoolkit-0.13.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
46
+ djresttoolkit-0.13.0.dist-info/entry_points.txt,sha256=YMhfTF-7mYppO8QqqWnvR_hyMWvoYxD6XI94_ViFu3k,60
47
+ djresttoolkit-0.13.0.dist-info/licenses/LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
48
+ djresttoolkit-0.13.0.dist-info/RECORD,,
@@ -1,3 +1,7 @@
1
1
  from ._exceptions import exception_handler
2
+ from ._api_views._choice_fields_apiview import ChoiceFieldsAPIView
2
3
 
3
- __all__ = ["exception_handler"]
4
+ __all__ = [
5
+ "exception_handler",
6
+ "ChoiceFieldsAPIView",
7
+ ]
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
+ )
@@ -0,0 +1,6 @@
1
+ from ._retrieve_object_mixin import RetrieveObjectMixin, QuerysetNotDefinedError
2
+
3
+ __all__ = [
4
+ "RetrieveObjectMixin",
5
+ "QuerysetNotDefinedError",
6
+ ]
@@ -0,0 +1,41 @@
1
+ from typing import Any
2
+ from django.db.models import Model, QuerySet
3
+
4
+
5
+ class QuerysetNotDefinedError(Exception):
6
+ """Exception raised when the `queryset` attribute is not set in the class."""
7
+
8
+ pass
9
+
10
+
11
+ class RetrieveObjectMixin[T: Model]:
12
+ """
13
+ Mixin to provide a method for retrieving a single model object by filters.
14
+
15
+ Requires the `queryset` attribute to be set in the class that inherits this mixin.
16
+
17
+ Example:
18
+ ```
19
+ class MyView(RetrieveModelMixin[Book], APIView):
20
+ queryset = Book.objects.all()
21
+
22
+ def get(self, request, *args, **kwargs):
23
+ obj = self.get_object(id=1)
24
+ return JsonResponse(obj.to_dict())
25
+ ```
26
+ """
27
+
28
+ queryset: QuerySet[T] | None = None
29
+
30
+ def get_object(self, **filters: Any) -> T | None:
31
+ """Retrieve a model object based on provided filters."""
32
+
33
+ if self.queryset is None:
34
+ raise QuerysetNotDefinedError(
35
+ "Queryset attribute is not set in the class.",
36
+ )
37
+
38
+ try:
39
+ return self.queryset.get(**filters)
40
+ except self.queryset.model.DoesNotExist:
41
+ return None