Output Django queryset as JSON

后端 未结 6 1700
陌清茗
陌清茗 2020-11-29 01:20

I want to serialize my queryset, and I want it in a format as this view outputs:

class JSONListView(ListView):
    queryset = Users.objects.all()

    def ge         


        
相关标签:
6条回答
  • 2020-11-29 01:45

    To return the queryset you retrieved with queryset = Users.objects.all(), you first need to serialize them.

    Serialization is the process of converting one data structure to another. Using Class-Based Views, you could return JSON like this.

    from django.core.serializers import serialize
    from django.http import JsonResponse
    from django.views.generic import View
    
    class JSONListView(View):
        def get(self, request, *args, **kwargs):
            qs = User.objects.all()
            data = serialize("json", qs)
            return JsonResponse(data)
    

    This will output a list of JSON. For more detail on how this works, check out my blog article How to return a JSON Response with Django. It goes into more detail on how you would go about this.

    0 讨论(0)
  • 2020-11-29 01:47

    For a efficient solution, you can use .values() function to get a list of dict objects and then dump it to json response by using i.e. JsonResponse (remember to set safe=False).

    Once you have your desired queryset object, transform it to JSON response like this:

    ...
    data = list(queryset.values())
    return JsonResponse(data, safe=False)
    

    You can specify field names in .values() function in order to return only wanted fields (the example above will return all model fields in json objects).

    0 讨论(0)
  • 2020-11-29 01:55

    It didn't work, because QuerySets are not JSON serializable.

    1) In case of json.dumps you have to explicitely convert your QuerySet to JSON serializable objects:

    class Model(model.Model):
        def as_dict(self):
            return {
                "id": self.id,
                # other stuff
            }
    

    And the serialization:

    dictionaries = [ obj.as_dict() for obj in self.get_queryset() ]
    return HttpResponse(json.dumps({"data": dictionaries}), content_type='application/json')
    

    2) In case of serializers. Serializers accept either JSON serializable object or QuerySet, but a dictionary containing a QuerySet is neither. Try this:

    serializers.serialize("json", self.get_queryset())
    

    Read more about it here:

    https://docs.djangoproject.com/en/dev/topics/serialization/

    0 讨论(0)
  • 2020-11-29 01:56

    You can use JsonResponse with values. Simple example:

    from django.http import JsonResponse
    
    def some_view(request):
        data = list(SomeModel.objects.values())  # wrap in list(), because QuerySet is not JSON serializable
        return JsonResponse(data, safe=False)  # or JsonResponse({'data': data})
    

    Or another approach with Django's built-in serializers:

    from django.core import serializers
    from django.http import HttpResponse
    
    def some_view(request):
        qs = SomeModel.objects.all()
        qs_json = serializers.serialize('json', qs)
        return HttpResponse(qs_json, content_type='application/json')
    

    In this case result is slightly different (without indent by default):

    [
        {
            "model": "some_app.some_model",
            "pk": 1,
            "fields": {
                "name": "Elon",
                "age": 48,
                ...
            }
        },
        ...
    ]
    

    I have to say, it is good practice to use something like marshmallow to serialize queryset.

    ...and a few notes for better performance:

    • use pagination if your queryset is big;
    • use objects.values() to specify list of required fields to avoid serialization and sending to client unnecessary model's fields (you also can pass fields to serializers.serialize);
    0 讨论(0)
  • 2020-11-29 01:56

    If the goal is to build an API that allow you to access your models in JSON format I recommend you to use the django-restframework that is an enormously popular package within the Django community to achieve this type of tasks.

    • Django Rest Framework Website
    • Github

    It include useful features such as Pagination, Defining Serializers, Nested models/relations and more. Even if you only want to do minor Javascript tasks and Ajax calls I would still suggest you to build a proper API using the Django Rest Framework instead of manually defining the JSON response.

    0 讨论(0)
  • 2020-11-29 02:02

    Try this:

    class JSONListView(ListView):
        queryset = Users.objects.all()
    
    
        def get(self, request, *args, **kwargs):
            data = {}
            data["users"] = get_json_list(queryset)
            return JSONResponse(data)
    
    
    def get_json_list(query_set):
        list_objects = []
        for obj in query_set:
            dict_obj = {}
            for field in obj._meta.get_fields():
                try:
                    if field.many_to_many:
                        dict_obj[field.name] = get_json_list(getattr(obj, field.name).all())
                        continue
                    dict_obj[field.name] = getattr(obj, field.name)
                except AttributeError:
                    continue
            list_objects.append(dict_obj)
        return list_objects
    
    0 讨论(0)
提交回复
热议问题