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 +118 -0
- {djresttoolkit-0.12.0.dist-info → djresttoolkit-0.14.0.dist-info}/METADATA +119 -1
- {djresttoolkit-0.12.0.dist-info → djresttoolkit-0.14.0.dist-info}/RECORD +10 -6
- src/djresttoolkit/urls/__init__.py +3 -0
- src/djresttoolkit/urls/_build_absolute_uri.py +33 -0
- src/djresttoolkit/views/mixins/__init__.py +6 -0
- src/djresttoolkit/views/mixins/_retrieve_object_mixin.py +41 -0
- {djresttoolkit-0.12.0.dist-info → djresttoolkit-0.14.0.dist-info}/WHEEL +0 -0
- {djresttoolkit-0.12.0.dist-info → djresttoolkit-0.14.0.dist-info}/entry_points.txt +0 -0
- {djresttoolkit-0.12.0.dist-info → djresttoolkit-0.14.0.dist-info}/licenses/LICENSE +0 -0
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.
|
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=
|
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
|
43
|
-
djresttoolkit
|
44
|
-
djresttoolkit-0.
|
45
|
-
djresttoolkit-0.
|
46
|
-
djresttoolkit-0.
|
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,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,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
|
File without changes
|
File without changes
|
File without changes
|