【Django】Django ORM - QuerySet 序列化

Posted by 西维蜀黍 on 2019-11-10, Last Modified on 2021-09-21

最完美的方法

解决:

  • ‘dict’ object has no attribute ‘_meta’
  • Queryset is not JSON serializable
users = models.User.objects.values(*USER_FIELDS).filter(**filter)[start_index:start_index + limit]
if type(resp) is not list:
   resp = list(resp)
return HttpResponse(json.dumps(resp, indent=2, cls=DjangoJSONEncoder), content_type="application/json")

Django 文档中提供的序列化方法

users = models.User.objects.filter(**filter)[start_index:start_index + 5]
data = serializers.serialize('json', users, fields=("id", "name", "join_time", "last_login_time", "type"))
return HttpResponse(data, content_type="application/json")

所有数据

from django.core import serializers
data = serializers.serialize("xml", SomeModel.objects.all())

部分数据

from django.core import serializers
data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size'))

使用 json.dumps 序列化

users = models.User.objects.values("id", "name", "join_time", "last_login_time", "type").filter(**filter)[start_index:start_index + 5]
a = json.dumps(list(users), cls=DjangoJSONEncoder)
return HttpResponse(a, content_type="application/json")

可能的报错

1 ‘dict’ object has no attribute ‘_meta’

Context

queryset = myModel.objects.filter(foo_icontains=bar).values('f1', 'f2', 'f3')
serialized_q = serializers.serialize('json', queryset, ensure_ascii=False)

Solution1

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:

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.

Solution2

Make list from objectQuerySet:

data_ready_for_json = list( ConventionCard.objects.filter(ownerUser = user).values('fileName','id') )
serialized_q = serializers.serialize('json', data_ready_for_json, ensure_ascii=False)

2 <type ’tuple’>: (‘datetime.datetime(2017, 6, 15, 0, 0, tzinfo=<UTC>) is not JSON serializable’,)

Context

views.py
users = models.User.objects.values("name","last_login_time").filter(**filter)[start_index:start_index + limit]
return HttpResponse(json.dumps(list(users), indent=2, cls=DjangoJSONEncoder), content_type="application/json")
models.py
class User(models.Model):
    name = models.CharField(max_length=20, unique=True,db_index=True)
    password = models.CharField(max_length=256)
    last_login_time = models.DateTimeField(null=True,blank=True)

可以看到,User 这个 model 的 last_login_time 域类型为DateTimeField。而当使用json.dumps进行序列化时,model 中有域的类型为DateTimeField时,就会出现datetime.datetime(...) is not JSON serializable 的错误。

Reference