Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion dynamic_rest/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,15 @@ def _get_queryset(self, queryset=None, serializer=None):
def _serializer_filter(self, serializer=None, queryset=None):
return serializer.filter_queryset(queryset)

def _get_id_fields(self, serializer, fields, is_root):
""" Return FK field names, with `_id` appended. """
get_id_fields = getattr(serializer, 'get_id_fields', lambda a: [])
if not is_root:
# For sideloads, return all ID fields they may be needed
# to related them to parent objects.
fields = None
return get_id_fields(fields)

def _build_queryset(
self,
serializer=None,
Expand Down Expand Up @@ -538,14 +547,19 @@ def _build_queryset(
not self.view.is_update() and
not self.view.is_delete()
):
id_fields = getattr(serializer, 'get_id_fields', lambda: [])()
id_fields = self._get_id_fields(serializer, fields, is_root_level)
# only include local model fields
only = [
field for field in set(
id_fields + list(requirements.keys())
) if is_model_field(model, field) and
not is_field_remote(model, field)
]
'''
print "Requirements: %s" % requirements
print "Fields: %s" % fields.keys()
print "Only: %s" % only
'''
queryset = queryset.only(*only)

# add request filters
Expand Down Expand Up @@ -622,6 +636,10 @@ def _serializer_filter(self, serializer=None, queryset=None):
)
return queryset

def _get_id_fields(self, serializer, fields, is_root_level):
get_id_fields = getattr(serializer, 'get_id_fields', lambda a: [])
return get_id_fields(fields)


class DynamicSortingFilter(OrderingFilter):

Expand Down
18 changes: 11 additions & 7 deletions dynamic_rest/prefetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,8 @@ def prefetch_related(self, *args):
return self

def only(self, *fields):
# TODO: support this for realz
'''
self.fields = set(self.fields) + set(fields)
'''
self.fields |= set(fields)
self.queryset = self.queryset.only(*fields)
return self

def exclude(self, *args, **kwargs):
Expand Down Expand Up @@ -251,7 +249,7 @@ def __init__(self, queryset):
self.queryset = queryset
self.model = queryset.model
self.prefetches = {}
self.fields = None
self.fields = set()
self.pk_field = queryset.model._meta.pk.attname
self._data = None
self._my_ids = None
Expand All @@ -267,7 +265,10 @@ def execute(self):
use_fastquery = getattr(self.model, 'USE_FASTQUERY', True)

if use_fastquery:
data = list(qs.values())
# print "Fields: %s" % self.fields
# print qs.query.__str__()
data = list(qs.values(*list(self.fields)))
# print data[0] if data else ''

self.merge_prefetch(data)
self._data = FastList(
Expand Down Expand Up @@ -412,7 +413,10 @@ def merge_o2or(self, data, field, prefetch, m2o_mode=False):
filter_args = {remote_filter_key: my_ids}

# Fetch remote objects
remote_objects = prefetch.query.filter(**filter_args).execute()
query = prefetch.query
if query.fields:
query = query.only(remote_field)
remote_objects = query.filter(**filter_args).execute()
id_map = self._make_id_map(data, pk_field=self.pk_field)

field_name = prefetch.field
Expand Down
14 changes: 12 additions & 2 deletions dynamic_rest/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,10 @@ def to_representation(self, instance):
Otherwise, a tagged data dict representation.
"""
if self.id_only():
return instance.pk
try:
return instance.pk
except AttributeError:
return instance
else:
if self.enable_optimization:
representation = self._faster_to_representation(instance)
Expand Down Expand Up @@ -720,7 +723,7 @@ class WithDynamicModelSerializerMixin(WithDynamicSerializerMixin):
def get_model(cls):
return getattr(cls.Meta, 'model', None)

def get_id_fields(self):
def get_id_fields(self, fields=None):
"""
Called to return a list of fields consisting of, at minimum,
the PK field name. The output of this method is used to
Expand All @@ -732,6 +735,11 @@ def get_id_fields(self):

out = [model._meta.pk.name] # get PK field name

if fields is not None:
sources = [f.source for f in fields.values()]
else:
sources = None # return all

# If this is being called, it means it
# is a many-relation to its parent.
# Django wants the FK to the parent,
Expand All @@ -741,6 +749,8 @@ def get_id_fields(self):
# TODO: We also might need to return all non-nullable fields,
# or else it is possible Django will issue another request.
for field in model._meta.fields:
if sources is not None and field.name not in sources:
continue
if isinstance(field, models.ForeignKey):
out.append(field.name + '_id')

Expand Down