48

I have a model that has many fields, however for this problem I only need 3 of those fields. When I try to serialize a .values set I get an exception:

'dict' object has no attribute '_meta'

This is my code:

queryset = myModel.objects.filter(foo_icontains=bar).values('f1', 'f2', 'f3')
serialized_q = serializers.serialize('json', queryset, ensure_ascii=False)
ivanleoncz
  • 9,070
  • 7
  • 57
  • 49
bash-
  • 6,144
  • 10
  • 43
  • 51

6 Answers6

56

As other people have said, Django's serializers can't handle a ValuesQuerySet. However, you can serialize by using a standard json.dumps() and transforming your ValuesQuerySet to a list by using list(). If your set includes Django fields such as Decimals, you will need to pass in DjangoJSONEncoder. Thus:

import json
from django.core.serializers.json import DjangoJSONEncoder

queryset = myModel.objects.filter(foo_icontains=bar).values('f1', 'f2', 'f3')
serialized_q = json.dumps(list(queryset), cls=DjangoJSONEncoder)
Andre Gregori
  • 1,150
  • 1
  • 10
  • 17
  • Finally, this helped me which I want the Queryset to be converted to JSON and then returned to the template. – Kyle_397 Mar 06 '20 at 14:28
41

Django serializers can only serialize queryset, values() does not return queryset rather ValuesQuerySet object. So, avoid using values(). Rather, specifiy the fields you wish to use in values(), in the serialize method as follows:

Look at this SO question for example

objectQuerySet = ConventionCard.objects.filter(ownerUser = user)
data = serializers.serialize('json', list(objectQuerySet), fields=('fileName','id'))

Instead of using objectQuerySet.values('fileName','id'), specify those fields using the fields parameter of serializers.serialize() as shown above.

Community
  • 1
  • 1
Davor Lucic
  • 28,970
  • 8
  • 66
  • 76
  • 2
    Yes I am aware that `.values()` returns a list, however simplejson.dumps gives me a `jsondata is not JSON serializable`, the `ValuesQuerySet` is in the form: `[{'key1': 'value1', 'key2': 'value2'}]` – bash- Oct 04 '11 at 16:06
  • Yes, it depends on what data looks like, the first example from the linked answer is what you are looking for. – Davor Lucic Oct 04 '11 at 16:06
  • 24
    @bash- just call `list()` on it first. – Daniel Roseman Oct 04 '11 at 16:08
  • 2
    Yes `list(ValuesQuerySet)` should return list which can then be serialized with `simplejson`. – Davor Lucic Oct 04 '11 at 16:11
  • thanks, just a side note, in the SO question you linked, does that approach query the db for all the fields and then subset it for the 2 fields or would it only query the db for just those 2 fields? – bash- Oct 04 '11 at 16:11
  • I think it would query all fields, you could perhaps use [`only`](https://docs.djangoproject.com/en/dev/ref/models/querysets/#only) when querying. Though I am not quite sure. [Debug it](http://stackoverflow.com/questions/3748295/getting-the-sql-from-a-django-queryset) to see how the query looks like. – Davor Lucic Oct 04 '11 at 16:14
  • Remember that will only work if you get one result. `list()` solution will work in both cases. – Davor Lucic Oct 04 '11 at 16:25
  • 1
    @rebus thanks, it didn't work before because there was a DecimalField and it couldn't be serialized – bash- Oct 04 '11 at 16:30
25

Make list from objectQuerySet:

data_ready_for_json = list( ConventionCard.objects.filter(ownerUser = user).values('fileName','id') )
laalto
  • 150,114
  • 66
  • 286
  • 303
Max
  • 519
  • 1
  • 7
  • 14
5

My solution, It's work fine

from django.core.serializers import serialize
import json

permission_list = Permission.objects.all().order_by('-id')
permission_serialize= json.loads(serialize('json', permission_list))
return JsonResponse({'data': permission_serialize})
Ashish Sondagar
  • 917
  • 1
  • 9
  • 16
  • Why do you `serialize()` and then `loads()` just to have the `JsonResponse` serialize the list again. This is extra, unnecessary work. – Code-Apprentice Jun 21 '21 at 15:10
2

Just cast to dict every item and create json with json.dumps:

json.dumps([dict(item) for item in SomeModel.objects.all().values('id', 'title')])
Pavel Patrin
  • 1,630
  • 1
  • 19
  • 33
0

Try this:

queryset = myModel.objects.filter(foo_icontains=bar)
serialized_q = serializers.serialize(queryset, many = True)
Ratan Sen
  • 1
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 05 '22 at 14:27