-
-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨Make
EagerLoading
mixin independent of DynamicFieldsMixin
- Introduce `RequestQueryParserMixin` used by both `DynamicFieldsMixiin` & `EagerLoadingMixin`, Closes #86 - Make query parameter name configurable through settings file, Closes #84
- Loading branch information
Showing
1 changed file
with
41 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
Serializer, ListSerializer, | ||
ValidationError | ||
) | ||
from django.db.models import Prefetch | ||
from django.conf import settings | ||
from django.db.models.fields.related import( | ||
ManyToOneRel, ManyToManyRel | ||
) | ||
|
@@ -18,36 +18,26 @@ | |
) | ||
|
||
|
||
class DynamicFieldsMixin(object): | ||
query_param_name = "query" | ||
|
||
def __init__(self, *args, **kwargs): | ||
# Don't pass 'query', 'fields' and 'exclude' kwargs to the superclass | ||
self.query = kwargs.pop('query', None) # Parsed query | ||
self.allowed_fields = kwargs.pop('fields', None) | ||
self.excluded_fields = kwargs.pop('exclude', None) | ||
self.return_pk = kwargs.pop('return_pk', False) | ||
|
||
is_field_kwarg_set = self.allowed_fields is not None | ||
is_exclude_kwarg_set = self.excluded_fields is not None | ||
msg = "May not set both `fields` and `exclude`" | ||
assert not(is_field_kwarg_set and is_exclude_kwarg_set), msg | ||
|
||
# Instantiate the superclass normally | ||
super().__init__(*args, **kwargs) | ||
|
||
def to_representation(self, instance): | ||
if self.return_pk: | ||
return instance.pk | ||
return super().to_representation(instance) | ||
class RequestQueryParserMixin(object): | ||
@staticmethod | ||
This comment has been minimized.
Sorry, something went wrong. |
||
def get_query_param_name(): | ||
DEFAULT_QUERY_PARAM_NAME = 'query' | ||
This comment has been minimized.
Sorry, something went wrong.
anudeepsamaiya
|
||
query_param_name = getattr( | ||
settings, | ||
"QUERY_PARAM_NAME", | ||
DEFAULT_QUERY_PARAM_NAME | ||
) | ||
return query_param_name | ||
This comment has been minimized.
Sorry, something went wrong.
anudeepsamaiya
|
||
|
||
@classmethod | ||
def has_query_param(cls, request): | ||
return cls.query_param_name in request.query_params | ||
query_param_name = cls.get_query_param_name() | ||
return query_param_name in request.query_params | ||
|
||
@classmethod | ||
def get_raw_query(cls, request): | ||
return request.query_params[cls.query_param_name] | ||
query_param_name = cls.get_query_param_name() | ||
return request.query_params[query_param_name] | ||
|
||
@classmethod | ||
def get_parsed_query_from_req(cls, request): | ||
|
@@ -64,6 +54,28 @@ def get_parsed_query_from_req(cls, request): | |
) | ||
raise ValidationError(msg) from None | ||
|
||
|
||
class DynamicFieldsMixin(RequestQueryParserMixin): | ||
def __init__(self, *args, **kwargs): | ||
# Don't pass 'query', 'fields' and 'exclude' kwargs to the superclass | ||
self.query = kwargs.pop('query', None) # Parsed query | ||
self.allowed_fields = kwargs.pop('fields', None) | ||
self.excluded_fields = kwargs.pop('exclude', None) | ||
self.return_pk = kwargs.pop('return_pk', False) | ||
|
||
is_field_kwarg_set = self.allowed_fields is not None | ||
is_exclude_kwarg_set = self.excluded_fields is not None | ||
msg = "May not set both `fields` and `exclude`" | ||
assert not(is_field_kwarg_set and is_exclude_kwarg_set), msg | ||
|
||
# Instantiate the superclass normally | ||
super().__init__(*args, **kwargs) | ||
|
||
def to_representation(self, instance): | ||
if self.return_pk: | ||
return instance.pk | ||
return super().to_representation(instance) | ||
|
||
def get_allowed_fields(self): | ||
fields = super().fields | ||
if self.allowed_fields is not None: | ||
|
@@ -268,20 +280,16 @@ def fields(self): | |
return {} | ||
|
||
|
||
class EagerLoadingMixin(object): | ||
class EagerLoadingMixin(RequestQueryParserMixin): | ||
@property | ||
def parsed_query(self): | ||
""" | ||
Gets parsed query for use in eager loading. | ||
Defaults to the serializer parsed query assuming | ||
using django-restql DynamicsFieldMixin. | ||
""" | ||
if hasattr(self, "get_serializer_class"): | ||
serializer_class = self.get_serializer_class() | ||
|
||
if issubclass(serializer_class, DynamicFieldsMixin): | ||
if serializer_class.has_query_param(self.request): | ||
return serializer_class.get_parsed_query_from_req(self.request) | ||
if self.has_query_param(self.request): | ||
return self.get_parsed_query_from_req(self.request) | ||
|
||
# Else include all fields | ||
query = { | ||
|
@@ -391,7 +399,7 @@ def get_queryset(self): | |
queryset = super().get_queryset() | ||
queryset = self.get_eager_queryset(queryset) | ||
return queryset | ||
|
||
|
||
class NestedCreateMixin(object): | ||
""" Create Mixin """ | ||
|
@yezyilomo here we can make a change by making this a
classmethod
. So if want to use aquery_param
from the child class I can use the class attribute.This will avoid introducing breaking changes for folks who already have defined a custom query name in child classes.
Ref #90