djangoserializationdjango-rest-frameworkdjango-querysetpaginator

Problem with .only() method, passing to Pagination / Serialization --- all fields are getting returned instead of the ones specified in only()


I am trying load some data into datatables. I am trying to specify columns in the model.objects query by using .only() --- at first glance at the resulting QuerySet, it does in fact look like the mySQL query is only asking for those columns.

However, When I try to pass the QuerySet into Paginator, and/or a Serializer, the result has ALL columns in it.

I cannot use .values_list() because that does not return the nested objects that I need to have serialized as part of my specific column ask. I am not sure what is happening to my .only()

db_result_object = model.objects.prefetch_related().filter(qs).order_by(asc+sort_by).only(*columns_to_return)

    paginated_results = Paginator(db_result_object,results_per_page)
    serialized_results = serializer(paginated_results.object_list,many=True)
    paginated_results.object_list = serialized_results.data

    return paginated_results

Solution

  • This one has tripped me up too. In Django, calling only() doesn't return data equivalent to a SQL statement like this:

    SELECT col_to_return_1, ... col_to_return_n
    FROM appname_model
    

    The reason it doesn't do it like this is because Django returns data to you not when you construct the QuerySet, but when you first access data from that QuerySet (see lazy QuerySets).

    In the case of only() (a specific example of what is called a deferred field) you still get all of the fields like you normally would, but the difference is that it isn't completely loaded in from the database immediately. When you access the data, it will only load the fields included in the only statement. Some useful docs here.

    My recommendation would be to write your Serializer so that it is only taking care of the one specific filed, likely using a SerializerMethodField with another serializer to serialize your related fields.