1

I wrote this Django view method:

def list_all_devices(request):

    all_devices_info = []
    fields = Devices.objects.all()
    for field in fields:
        device = Devices.objects.filter(device_id=field.device_id).values()
        dev = device[0]

        dev['variables'] = Variables.objects.filter(device_id=field.device_id).values()

        del dev['device_creation_datetime']
        all_devices_info.append(dev)

    return HttpResponse(json.dumps(all_devices_info), content_type="application/json")

For some reason the first code doesn't work, but if I do a minor modification like the following, it starts working, I can't figure out why.

def list_all_devices(request):

    all_devices_info = []
    fields = Devices.objects.all()
    for field in fields:
        device = Devices.objects.filter(device_id=field.device_id).values()
        dev = device[0]

        dev['variables'] = [v for v in Variables.objects.filter(device_id=field.device_id).values()]

        del dev['device_creation_datetime']
        all_devices_info.append(dev)

    return HttpResponse(json.dumps(all_devices_info), content_type="application/json")

When I analyze the modifications:

[v for v in Variables.objects.filter(device_id=field.device_id).values()]

and

Variables.objects.filter(device_id=field.device_id).values()

they seem similar, and both seem to be lists and have the same information inside. But when the json.dumps method is called over it, in the first code it throws the following error on the browser.

enter image description here

xyres
  • 20,487
  • 3
  • 56
  • 85
LPS
  • 375
  • 3
  • 16
  • You're right: both the expressions give you a list, but both lists are very different. As pointed in the answer below, the `[v for v ...]` gives you a *normal* Python list, whereas `Variable...values()` expression gives a Django querydict, which also is a list, but with some extra methods and attributes. – xyres Dec 16 '15 at 05:02
  • See this question: [ is not JSON serializable](http://stackoverflow.com/questions/16790375/django-object-is-not-json-serializable). – xyres Dec 16 '15 at 05:04

2 Answers2

1

values() doesn't return a simple data type.

I tried with a django model:

dir(myModel.objects.all().values())

['and', 'bool', 'class', 'deepcopy', 'delattr', 'dict', 'doc', 'format', 'getattribute', 'getitem', 'getstate', 'hash', 'init', 'iter', 'len', 'module', 'new', 'nonzero', 'or', 'reduce', 'reduce_ex', 'repr', 'setattr', 'setstate', 'sizeof', 'str', 'subclasshook', 'weakref', '_add_hints', '_as_sql', '_base_queryset_class', '_batched_insert', '_clone', '_create_object_from_params', '_db', '_earliest_or_latest', '_extract_model_params', '_fetch_all', '_fields', '_filter_or_exclude', '_for_write', '_has_filters', '_hints', '_insert', '_known_related_objects', '_merge_known_related_objects', '_merge_sanity_check', '_next_is_sticky', '_populate_pk_values', '_prefetch_done', '_prefetch_related_lookups', '_prefetch_related_objects', '_prepare', '_raw_delete', '_result_cache', '_setup_aggregate_query', '_setup_query', '_specialized_queryset_class', '_sticky_filter', '_update', 'aggregate', 'all', 'annotate', 'annotation_names', 'as_manager', 'bulk_create', 'complex_filter', 'count', 'create', 'dates', 'datetimes', 'db', 'defer', 'delete', 'distinct', 'earliest', 'exclude', 'exists', 'extra', 'extra_names', 'field_names', 'filter', 'first', 'get', 'get_or_create', 'in_bulk', 'is_compatible_query_object_type', 'iterator', 'last', 'latest', 'model', 'none', 'only', 'order_by', 'ordered', 'prefetch_related', 'query', 'raw', 'reverse', 'select_for_update', 'select_related', 'update', 'update_or_create', 'using', 'value_annotation', 'values', 'values_list']

And this is the dir for a python array:

dir([])

['add', 'class', 'contains', 'delattr', 'delitem', 'delslice', 'doc', 'eq', 'format', 'ge', 'getattribute', 'getitem', 'getslice', 'gt', 'hash', 'iadd', 'imul', 'init', 'iter', 'le', 'len', 'lt', 'mul', 'ne', 'new', 'reduce', 'reduce_ex', 'repr', 'reversed', 'rmul', 'setattr', 'setitem', 'setslice', 'sizeof', 'str', 'subclasshook', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

Admdebian
  • 630
  • 6
  • 17
1

Devices.objects.filter(device_id=field.device_id).values() is ValuesQuerySet which is derived from QuerySet and both of then are unevaluated which means that is a query yet is not executed on database until you apply list or iterate on it. When you use json.dumps you need data not query.

Apply following to see the types:

Devices.objects.filter(device_id=field.device_id).values().__class__

django.db.models.query.ValuesQuerySet

Devices.objects.filter(device_id=field.device_id).values().__class__.__base__

django.db.models.query.QuerySet

Serjik
  • 10,543
  • 8
  • 61
  • 70