Skip to content

Commit

Permalink
✨Make EagerLoading mixin independent of DynamicFieldsMixin
Browse files Browse the repository at this point in the history
- Introduce `RequestQueryParserMixin` used by both `DynamicFieldsMixiin` & `EagerLoadingMixin`, Closes #86
- Make query parameter name configurable through settings file, Closes #84
  • Loading branch information
yezyilomo committed Nov 25, 2019
1 parent 9a7e63b commit 7364577
Showing 1 changed file with 41 additions and 33 deletions.
74 changes: 41 additions & 33 deletions django_restql/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand All @@ -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.

Copy link
@anudeepsamaiya

anudeepsamaiya Nov 26, 2019

@yezyilomo here we can make a change by making this a classmethod. So if want to use a query_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

def get_query_param_name():
DEFAULT_QUERY_PARAM_NAME = 'query'

This comment has been minimized.

Copy link
@anudeepsamaiya

anudeepsamaiya Nov 26, 2019

@yezyilomo DEFAULT_QUERY_PARAM_NAME should be class variable.

query_param_name = getattr(
settings,
"QUERY_PARAM_NAME",
DEFAULT_QUERY_PARAM_NAME
)
return query_param_name

This comment has been minimized.

Copy link
@anudeepsamaiya

anudeepsamaiya Nov 26, 2019

This classmethod should be returning cls.query_param_name or query_param_name


@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):
Expand All @@ -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:
Expand Down Expand Up @@ -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 = {
Expand Down Expand Up @@ -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 """
Expand Down

0 comments on commit 7364577

Please sign in to comment.