Convert the queryset on values_list() will be more memory efficient than on values() directly. Since the method values() returns a queryset of list of dict (key:value pairs), values_list() only returns list of tuple (pure data). It will save about 50% memory, just need to set the column information when you call pd.DataFrame().
Method 1:
queryset = models.xxx.objects.values("A","B","C","D")
df = pd.DataFrame(list(queryset)) ## consumes much memory
#df = pd.DataFrame.from_records(queryset) ## works but no much change on memory usage
Method 2:
queryset = models.xxx.objects.values_list("A","B","C","D")
df = pd.DataFrame(list(queryset), columns=["A","B","C","D"]) ## this will save 50% memory
#df = pd.DataFrame.from_records(queryset, columns=["A","B","C","D"]) ##It does not work. Crashed with datatype is queryset not list.