LPS
LPS

Reputation: 385

Django view code has weird behaviour

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

Upvotes: 1

Views: 236

Answers (2)

Serjik
Serjik

Reputation: 10931

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

Upvotes: 1

Admdebian
Admdebian

Reputation: 660

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']

Upvotes: 1

Related Questions