<Đối tượng Django> không thể tuần tự hóa JSON


102

Tôi có mã sau để tuần tự hóa bộ truy vấn;

def render_to_response(self, context, **response_kwargs):

    return HttpResponse(json.simplejson.dumps(list(self.get_queryset())),
                        mimetype="application/json")

Và sau đây là của tôi get_querset()

[{'product': <Product: hederello ()>, u'_id': u'9802', u'_source': {u'code': u'23981', u'facilities': [{u'facility': {u'name': {u'fr': u'G\xe9n\xe9ral', u'en': u'General'}, u'value': {u'fr': [u'bar', u'r\xe9ception ouverte 24h/24', u'chambres non-fumeurs', u'chambres familiales',.........]}]

Mà tôi cần đăng nhiều kỳ. Nhưng nó nói rằng không thể tuần tự hóa <Product: hederello ()>. Bởi vì danh sách bao gồm cả đối tượng django và dicts. Bất kỳ ý tưởng?


Câu trả lời:


114

simplejsonjsonkhông hoạt động tốt với các đối tượng django.

Trình tuần tự tích hợp của Django chỉ có thể tuần tự hóa các tập truy vấn chứa đầy các đối tượng django:

data = serializers.serialize('json', self.get_queryset())
return HttpResponse(data, content_type="application/json")

Trong trường hợp của bạn, self.get_queryset()chứa một hỗn hợp các đối tượng django và di chuyển bên trong.

Một tùy chọn là loại bỏ các phiên bản mô hình trong self.get_queryset()và thay thế chúng bằng các phiên bản bằng cách sử dụng model_to_dict:

from django.forms.models import model_to_dict

data = self.get_queryset()

for item in data:
   item['product'] = model_to_dict(item['product'])

return HttpResponse(json.simplejson.dumps(data), mimetype="application/json")

Hy vọng rằng sẽ giúp.


Hiện đang gặp lỗi -> 'NoneType' object has no attribute 'concrete_model'... Và đang sử dụng Django 1.4+
cá ngừ

3
Khi mô hình có trường ngày giờ, nó không hoạt động.
ax003d

giải pháp đó sẽ kích hoạt rất nhiều truy vấn
Julio Marins

để sử dụng trực tiếp trong JS, chỉ cần sử dụng safetage. stackoverflow.com/a/57939897/4157431
Rami Alloush 14/09/19

62

Cách dễ nhất là sử dụng JsonResponse .

Đối với bộ truy vấn, bạn nên chuyển danh sách các bộ truy vấn valuesđó, như sau:

from django.http import JsonResponse

queryset = YourModel.objects.filter(some__filter="some value").values()
return JsonResponse({"models_to_return": list(queryset)})

2
cảm ơn vì .values (), Trong trường hợp của tôi, tôi chỉ cần thêm .values () sau khi lọc
Jze

18

Tôi thấy rằng điều này có thể được thực hiện khá đơn giản bằng cách sử dụng phương thức ".values", cũng cung cấp cho các trường được đặt tên:

result_list = list(my_queryset.values('first_named_field', 'second_named_field'))
return HttpResponse(json.dumps(result_list))

"list" phải được sử dụng để lấy dữ liệu dưới dạng có thể lặp lại, vì kiểu "value queryset" chỉ là một dict nếu được chọn dưới dạng có thể lặp lại.

Tài liệu: https://docs.djangoproject.com/en/1.7/ref/models/querysets/#values


Điều này làm việc tốt cho tôi. Mặc dù thông báo lỗi cho thấy tất cả đều nằm trong một danh sách lớn, nhưng list()vẫn cần thiết.
trpt4him

1
Giải pháp đơn giản nhất và tốt nhất
Timur

11

Từ phiên bản 1.9 Cách nhận json chính thức và dễ dàng hơn

from django.http import JsonResponse
from django.forms.models import model_to_dict


return JsonResponse(  model_to_dict(modelinstance) )

8

Lập trình viên js của chúng tôi đã yêu cầu tôi trả lại dữ liệu định dạng JSON chính xác thay vì một chuỗi mã hóa json cho cô ấy.

Dưới đây là giải pháp. (Điều này sẽ trả về một đối tượng có thể được sử dụng / xem trực tiếp trong trình duyệt)

import json
from xxx.models import alert
from django.core import serializers

def test(request):
    alert_list = alert.objects.all()

    tmpJson = serializers.serialize("json",alert_list)
    tmpObj = json.loads(tmpJson)

    return HttpResponse(json.dumps(tmpObj))

Sẽ tốt hơn chỉHttpResponse(tmpObj)
Pablo Díaz

6

Đầu tiên, tôi đã thêm một phương thức to_dict vào mô hình của mình;

def to_dict(self):
    return {"name": self.woo, "title": self.foo}

Sau đó, tôi có cái này;

class DjangoJSONEncoder(JSONEncoder):

    def default(self, obj):
        if isinstance(obj, models.Model):
            return obj.to_dict()
        return JSONEncoder.default(self, obj)


dumps = curry(dumps, cls=DjangoJSONEncoder)

và cuối cùng sử dụng lớp này để tuần tự hóa bộ truy vấn của tôi.

def render_to_response(self, context, **response_kwargs):
    return HttpResponse(dumps(self.get_queryset()))

Điều này hoạt động khá tốt

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.