|
11 | 11 | from django.db.models.manager import Manager
|
12 | 12 | from django.db.models.query import QuerySet
|
13 | 13 | from django.urls import NoReverseMatch
|
| 14 | +from django.utils.module_loading import import_string as import_class_from_dotted_path |
14 | 15 | from rest_framework import generics, viewsets
|
15 | 16 | from rest_framework.exceptions import MethodNotAllowed, NotFound
|
16 | 17 | from rest_framework.fields import get_attribute
|
|
30 | 31 | )
|
31 | 32 |
|
32 | 33 |
|
33 |
| -class PreloadIncludesMixin(object): |
34 |
| - """ |
35 |
| - This mixin provides a helper attributes to select or prefetch related models |
36 |
| - based on the include specified in the URL. |
37 |
| -
|
38 |
| - __all__ can be used to specify a prefetch which should be done regardless of the include |
39 |
| -
|
40 |
| -
|
41 |
| - .. code:: python |
42 |
| -
|
43 |
| - # When MyViewSet is called with ?include=author it will prefetch author and authorbio |
44 |
| - class MyViewSet(viewsets.ModelViewSet): |
45 |
| - queryset = Book.objects.all() |
46 |
| - prefetch_for_includes = { |
47 |
| - '__all__': [], |
48 |
| - 'category.section': ['category'] |
49 |
| - } |
50 |
| - select_for_includes = { |
51 |
| - '__all__': [], |
52 |
| - 'author': ['author', 'author__authorbio'], |
53 |
| - } |
54 |
| - """ |
55 |
| - |
56 |
| - def get_select_related(self, include): |
57 |
| - return getattr(self, "select_for_includes", {}).get(include, None) |
58 |
| - |
59 |
| - def get_prefetch_related(self, include): |
60 |
| - return getattr(self, "prefetch_for_includes", {}).get(include, None) |
61 |
| - |
62 |
| - def get_queryset(self, *args, **kwargs): |
63 |
| - qs = super(PreloadIncludesMixin, self).get_queryset(*args, **kwargs) |
64 |
| - |
65 |
| - included_resources = get_included_resources( |
66 |
| - self.request, self.get_serializer_class() |
67 |
| - ) |
68 |
| - for included in included_resources + ["__all__"]: |
69 |
| - |
70 |
| - select_related = self.get_select_related(included) |
71 |
| - if select_related is not None: |
72 |
| - qs = qs.select_related(*select_related) |
73 |
| - |
74 |
| - prefetch_related = self.get_prefetch_related(included) |
75 |
| - if prefetch_related is not None: |
76 |
| - qs = qs.prefetch_related(*prefetch_related) |
77 |
| - |
78 |
| - return qs |
79 |
| - |
80 |
| - |
81 | 34 | class AutoPrefetchMixin(object):
|
82 | 35 | def get_queryset(self, *args, **kwargs):
|
83 | 36 | """This mixin adds automatic prefetching for OneToOne and ManyToMany fields."""
|
@@ -182,6 +135,8 @@ def get_related_serializer_class(self):
|
182 | 135 | False
|
183 | 136 | ), 'Either "included_serializers" or "related_serializers" should be configured'
|
184 | 137 |
|
| 138 | + if not isinstance(_class, type): |
| 139 | + return import_class_from_dotted_path(_class) |
185 | 140 | return _class
|
186 | 141 |
|
187 | 142 | return parent_serializer_class
|
@@ -215,13 +170,13 @@ def get_related_instance(self):
|
215 | 170 |
|
216 | 171 |
|
217 | 172 | class ModelViewSet(
|
218 |
| - AutoPrefetchMixin, PreloadIncludesMixin, RelatedMixin, viewsets.ModelViewSet |
| 173 | + AutoPrefetchMixin, RelatedMixin, viewsets.ModelViewSet |
219 | 174 | ):
|
220 | 175 | http_method_names = ["get", "post", "patch", "delete", "head", "options"]
|
221 | 176 |
|
222 | 177 |
|
223 | 178 | class ReadOnlyModelViewSet(
|
224 |
| - AutoPrefetchMixin, PreloadIncludesMixin, RelatedMixin, viewsets.ReadOnlyModelViewSet |
| 179 | + AutoPrefetchMixin, RelatedMixin, viewsets.ReadOnlyModelViewSet |
225 | 180 | ):
|
226 | 181 | http_method_names = ["get", "post", "patch", "delete", "head", "options"]
|
227 | 182 |
|
|
0 commit comments