djresttoolkit 0.12.0__py3-none-any.whl → 0.14.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
@@ -695,6 +695,124 @@ urlpatterns = [
695
695
  - Useful for frontend forms or API consumers that need selectable options.
696
696
  - Integrates seamlessly with `ModelChoiceFieldMixin` from `djresttoolkit`.
697
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
+
752
+ ### 13. build_absolute_uri — API Reference
753
+
754
+ ```python
755
+ from djresttoolkit.urls import build_absolute_uri
756
+ ```
757
+
758
+ #### build absolute uri Description
759
+
760
+ - Builds a **fully qualified absolute URL** for a Django or DRF view.
761
+ - Optionally includes **query parameters**.
762
+ - Works with both **Django `HttpRequest`** and **DRF `Request`** objects.
763
+ - Uses Django's `reverse()` to dynamically resolve URL names.
764
+
765
+ #### build absolute uri Function Signature
766
+
767
+ ```python
768
+ def build_absolute_uri(
769
+ request: HttpRequest | Request,
770
+ url_name: str,
771
+ query_params: dict[str, Any] | None = None,
772
+ *args: Any,
773
+ **kwargs: Any,
774
+ ) -> str:
775
+ ...
776
+ ```
777
+
778
+ ---
779
+
780
+ #### build absolute uri Parameters
781
+
782
+ - `request` (`HttpRequest | Request`): The incoming Django or DRF request object.
783
+ - `url_name` (`str`): Name of the URL pattern to reverse.
784
+ - `query_params` (`dict[str, Any] | None`): Optional dictionary of query parameters to append to the URL.
785
+ - `*args` (`Any`): Positional arguments for the URL reversal.
786
+ - `**kwargs` (`Any`): Keyword arguments for the URL reversal.
787
+
788
+ ---
789
+
790
+ ### build absolute uri Returns
791
+
792
+ - `str`: Absolute URI of the view including optional query parameters.
793
+
794
+ ### Example of build absolute uri
795
+
796
+ ```python
797
+ from django.http import HttpRequest
798
+ from djresttoolkit.utils import build_absolute_uri
799
+
800
+ def my_view(request: HttpRequest):
801
+ absolute_url = build_absolute_uri(
802
+ request,
803
+ url_name="book-detail",
804
+ query_params={"ref": "newsletter"},
805
+ pk=123
806
+ )
807
+ return HttpResponse(f"URL: {absolute_url}")
808
+ ```
809
+
810
+ **Output Example:**
811
+
812
+ ```url
813
+ https://example.com/api/books/123/?ref=newsletter
814
+ ```
815
+
698
816
  ## 🛠️ Planned Features
699
817
 
700
818
  - Add more utils
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: djresttoolkit
3
- Version: 0.12.0
3
+ Version: 0.14.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
@@ -753,6 +753,124 @@ urlpatterns = [
753
753
  - Useful for frontend forms or API consumers that need selectable options.
754
754
  - Integrates seamlessly with `ModelChoiceFieldMixin` from `djresttoolkit`.
755
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
+
810
+ ### 13. build_absolute_uri — API Reference
811
+
812
+ ```python
813
+ from djresttoolkit.urls import build_absolute_uri
814
+ ```
815
+
816
+ #### build absolute uri Description
817
+
818
+ - Builds a **fully qualified absolute URL** for a Django or DRF view.
819
+ - Optionally includes **query parameters**.
820
+ - Works with both **Django `HttpRequest`** and **DRF `Request`** objects.
821
+ - Uses Django's `reverse()` to dynamically resolve URL names.
822
+
823
+ #### build absolute uri Function Signature
824
+
825
+ ```python
826
+ def build_absolute_uri(
827
+ request: HttpRequest | Request,
828
+ url_name: str,
829
+ query_params: dict[str, Any] | None = None,
830
+ *args: Any,
831
+ **kwargs: Any,
832
+ ) -> str:
833
+ ...
834
+ ```
835
+
836
+ ---
837
+
838
+ #### build absolute uri Parameters
839
+
840
+ - `request` (`HttpRequest | Request`): The incoming Django or DRF request object.
841
+ - `url_name` (`str`): Name of the URL pattern to reverse.
842
+ - `query_params` (`dict[str, Any] | None`): Optional dictionary of query parameters to append to the URL.
843
+ - `*args` (`Any`): Positional arguments for the URL reversal.
844
+ - `**kwargs` (`Any`): Keyword arguments for the URL reversal.
845
+
846
+ ---
847
+
848
+ ### build absolute uri Returns
849
+
850
+ - `str`: Absolute URI of the view including optional query parameters.
851
+
852
+ ### Example of build absolute uri
853
+
854
+ ```python
855
+ from django.http import HttpRequest
856
+ from djresttoolkit.utils import build_absolute_uri
857
+
858
+ def my_view(request: HttpRequest):
859
+ absolute_url = build_absolute_uri(
860
+ request,
861
+ url_name="book-detail",
862
+ query_params={"ref": "newsletter"},
863
+ pk=123
864
+ )
865
+ return HttpResponse(f"URL: {absolute_url}")
866
+ ```
867
+
868
+ **Output Example:**
869
+
870
+ ```url
871
+ https://example.com/api/books/123/?ref=newsletter
872
+ ```
873
+
756
874
  ## 🛠️ Planned Features
757
875
 
758
876
  - Add more utils
@@ -1,5 +1,5 @@
1
1
  LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
2
- README.md,sha256=swcg_Yd0tKwp4PDXQn7gfj7HKpwLs-UPV4jvqOHvHvQ,18485
2
+ README.md,sha256=VZKLjTbak58sMkj073lXbWJVrxZk3VqPS1wIhuqmu7U,21729
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,13 +34,17 @@ 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/urls/__init__.py,sha256=u-Hj8GARO0mWZwiehCi3VslMXqtkdAFff7VcXVuiN8w,86
38
+ src/djresttoolkit/urls/_build_absolute_uri.py,sha256=X9kdoTRGIJ2ordpkHgSXmqwmmMT-OZBgluV5ULUhJEk,915
37
39
  src/djresttoolkit/views/__init__.py,sha256=QuJ9C0Vfzkfrwyqzunxh-A-aErmS6yOoy0uzjDu3oG8,177
38
40
  src/djresttoolkit/views/_api_views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
41
  src/djresttoolkit/views/_api_views/_choice_fields_apiview.py,sha256=zABPgqxMVaWd814B_sC64bWL61fDJkyYQZmJXQCa6Xc,1395
40
42
  src/djresttoolkit/views/_exceptions/__init__.py,sha256=DrCUxuPNyBR4WhzNutn5HDxLa--q51ykIxSG7_bFsOI,83
41
43
  src/djresttoolkit/views/_exceptions/_exception_handler.py,sha256=_o7If47bzWLl57LeSXSWsIDsJGo2RIpwYAwNQ-hsHVY,2839
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,,
44
+ src/djresttoolkit/views/mixins/__init__.py,sha256=K-1tk5d8tCVViMynw5DdffJ3Oo5uHpEx32E3_4X2UxM,154
45
+ src/djresttoolkit/views/mixins/_retrieve_object_mixin.py,sha256=Q9znYPb07YXXUhsL7VIrk3BC-zDwjOhwLJKe2GPJ-k0,1155
46
+ djresttoolkit-0.14.0.dist-info/METADATA,sha256=rYNwwhrKT4i3RuKPMFC6l1xU8yzJkcd7vC8rkYeeOsc,24739
47
+ djresttoolkit-0.14.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
48
+ djresttoolkit-0.14.0.dist-info/entry_points.txt,sha256=YMhfTF-7mYppO8QqqWnvR_hyMWvoYxD6XI94_ViFu3k,60
49
+ djresttoolkit-0.14.0.dist-info/licenses/LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
50
+ djresttoolkit-0.14.0.dist-info/RECORD,,
@@ -0,0 +1,3 @@
1
+ from ._build_absolute_uri import build_absolute_uri
2
+
3
+ __all__ = ["build_absolute_uri"]
@@ -0,0 +1,33 @@
1
+ from typing import Any
2
+ from urllib.parse import urlencode
3
+ from django.http import HttpRequest
4
+ from django.urls import reverse
5
+ from rest_framework.request import Request
6
+
7
+
8
+ def build_absolute_uri(
9
+ request: HttpRequest | Request,
10
+ url_name: str,
11
+ query_params: dict[str, Any] | None = None,
12
+ *args: Any,
13
+ **kwargs: Any,
14
+ ) -> str:
15
+ """
16
+ Build an absolute URI for a given Django or DRF view.
17
+
18
+ Args:
19
+ request: Django or DRF request object.
20
+ url_name: Name of the URL pattern to reverse.
21
+ query_params: Optional dictionary of query parameters.
22
+ *args: Positional arguments for the URL.
23
+ **kwargs: Keyword arguments for the URL.
24
+
25
+ Returns:
26
+ Absolute URI as a string.
27
+ """
28
+ url = reverse(url_name, args=args, kwargs=kwargs)
29
+
30
+ if query_params:
31
+ url += f"?{urlencode(query_params, doseq=True)}"
32
+
33
+ return request.build_absolute_uri(url)
@@ -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