DRF: Serializer Group By Model Field

2024/9/29 15:31:36

I want my api to return Account objects grouped by the account_type field in the model. I want to do this so that the grouped accounts are easier to access in my JS code. This is what is returned now:

[{"id": 6,"owner": 1,"account_name": "Credit Card 1","account_type": "credit card","created_time": "2019-07-18T02:57:44.288654Z","modified_time": "2019-07-18T02:57:44.288842Z"
}, {"id": 11,"owner": 1,"account_name": "Savings 1","account_type": "savings","created_time": "2019-07-18T03:00:22.122226Z","modified_time": "2019-07-18T03:00:22.122283Z"
}, {"id": 5,"owner": 1,"account_name": "Checking 1","account_type": "checking","created_time": "2019-07-18T02:57:28.580268Z","modified_time": "2019-07-18T02:57:28.580305Z"
}, {"id": 9,"owner": 1,"account_name": "Savings 2","account_type": "savings","created_time": "2019-07-18T02:59:57.156837Z","modified_time": "2019-07-18T02:59:57.156875Z"
}, {"id": 10,"owner": 1,"account_name": "Savings 3","account_type": "savings","created_time": "2019-07-18T03:00:12.873799Z","modified_time": "2019-07-18T03:00:12.873846Z"
}, {"id": 7,"owner": 1,"account_name": "Credit Card 2","account_type": "credit card","created_time": "2019-07-18T02:57:55.921586Z","modified_time": "2019-07-18T02:57:55.921613Z"
}]

And I'd like it to return something like this:

{"credit card": [{   "id": 6,"owner": 1,"account_name": "Credit Card 1","account_type": "credit card","created_time": "2019-07-18T02:57:44.288654Z","modified_time": "2019-07-18T02:57:44.288842Z"},{"id": 7,"owner": 1,"account_name": "Credit Card 2","account_type": "credit card","created_time": "2019-07-18T02:57:55.921586Z","modified_time": "2019-07-18T02:57:55.921613Z"}  ],"savings": [{"id": 11,"owner": 1,"account_name": "Savings 1","account_type": "savings","created_time": "2019-07-18T03:00:22.122226Z","modified_time": "2019-07-18T03:00:22.122283Z"},{"id": 9,"owner": 1,"account_name": "Savings 2","account_type": "savings","created_time": "2019-07-18T02:59:57.156837Z","modified_time": "2019-07-18T02:59:57.156875Z"},{"id": 10,"owner": 1,"account_name": "Savings 3","account_type": "savings","created_time": "2019-07-18T03:00:12.873799Z","modified_time": "2019-07-18T03:00:12.873846Z"}],"checking": [{"id": 5,"owner": 1,"account_name": "Checking 1","account_type": "checking","created_time": "2019-07-18T02:57:28.580268Z","modified_time": "2019-07-18T02:57:28.580305Z"}]
}

Model:

class Account(models.Model):CHECKING = 'checking'CREDIT_CARD = 'credit card'SAVINGS = 'savings'ACCOUNT_TYPE_CHOICES = [(CHECKING, 'Checking'),(CREDIT_CARD, 'Credit Card'),(SAVINGS, 'Savings'),]owner = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)account_name = models.CharField(max_length=128,null=False)account_type = models.CharField(max_length=128,null=False,choices=ACCOUNT_TYPE_CHOICES)created_time = models.DateTimeField(auto_now_add=True)modified_time = models.DateTimeField(auto_now=True)

Serializer:

class AccountSerializer(serializers.ModelSerializer):class Meta:model = Accountfields = ('id','owner','account_name','account_type','created_time','modified_time')def create(self, validated_data):account = Account.objects.create(**validated_data)return account

Edit: Adding my views.py because I'm curious if that's the issue.

class AccountViewSet(viewsets.ModelViewSet):queryset = Account.objects.all().order_by('account_name')# serializer_class = AccountSerializerserializer_class = AccountByTypeSerializerdef list(self, request, *args, **kwargs):page = self.paginate_queryset(self.queryset)if page is not None:serializer = self.get_serializer(page, many=True)return self.get_paginated_response(serializer.data)def retrieve(self, request, pk, *args, **kwargs):instance = self.get_object()serializer = self.get_serializer(instance)return Response(serializer.data)def create(self, request, *args, **kwargs):serializer = self.get_serializer(data=request.data)serializer.is_valid(raise_exception=True)self.perform_create(serializer)headers = self.get_success_headers(serializer.data)return Response(serializer.data,status=status.HTTP_201_CREATED,headers=headers)def update(self, request, *args, **kwargs):# partial = kwargs.pop('partial', False)instance = self.get_object()serializer = self.get_serializer(instance,data=request.data,partial=True)serializer.is_valid(raise_exception=True)self.perform_update(serializer)return Response(serializer.data)
Answer

Since you have only a limited amount of account type choices, you can use SerializerMethodFields, like this:

class AccountByTypeSerializer(serializers.ModelSerializer):checking = serializers.SerializerMethodField()savings = serializers.SerializerMethodField()credit_card = serializers.SerializerMethodField()def _build_account_list(account_type):accounts = Account.objects.filter(account_type=account_type)serializer = AccountSerializer(accounts, many=True)return serializer.datadef get_savings(self, obj):return self._build_account_list(Account.SAVINGS)...class Meta:model = Accountfields = ('checking', 'savings', 'credit_card')

I suggest you to use credit_card instead of credit card, but if you really need to use the latter, just override to_representation.

https://en.xdnf.cn/q/71198.html

Related Q&A

Need help combining two 3 channel images into 6 channel image Python

I am trying to combine two different RGB images into a single 6 channel image (Tiff is best) using nothing but Python.What I have is an RGB image taken from a normal camera as well as another RGB image…

Komodo Edit disable autocomple

I am using Komodo Edit 8 and its autocomplete feature is totally annoying. As soon as I type "for i" , it autofills in this:for i in range:codeNow i have to delete it manually to continue typ…

Python WeakKeyDictionary for unhashable types

As raised in cpython issue 88306, python WeakKeyDictionary fails for non hashable types. According to the discussion in the python issue above, this is an unnecessary restriction, using ids of the keys…

Django MPTT efficiently serializing relational data with DRF

I have a Category model that is a MPTT model. It is m2m to Group and I need to serialize the tree with related counts, imagine my Category tree is this:Root (related to 1 group)- Branch (related to 2 g…

Psycopg2: module object has no attribute connect [duplicate]

This question already has answers here:Importing a library from (or near) a script with the same name raises "AttributeError: module has no attribute" or an ImportError or NameError(4 answers…

matplotlib text not clipped

When drawing text in matplotlib with text(), and then interactively panning the image, the resulting drawn text is not clipped to the data window. This is counter to how plotting data or drawing text …

how to make child class call parent class __init__ automatically?

i had a class called CacheObject,and many class extend from it.now i need to add something common on all classes from this class so i write thisclass CacheObject(object):def __init__(self):self.updated…

Creating a dataframe in pandas by multiplying two series together

Say I have two series in pandas, series A and series B. How do I create a dataframe in which all of those values are multiplied together, i.e. with series A down the left hand side and series B along t…

UnicodeDecodeError in PyCharm debugger

Its a reference to UnicodeDecodeError while using cyryllic .I have same problem with Python 3.3 and Pycharm 2.7.2 Tryed to hardcode encoding in code, manually specifying encoding in Pycharm options, bu…

Scipy griddata with linear and cubic yields nan

the following code should produce griddata. But in case I choose as interpolation type cubic or linear I am getting nans in the z grid. Wen im choosing nearest everything is running fine. Here is an ex…