Python DRF:按模型字段的序列化程序组
我希望api返回模型中按Python DRF:按模型字段的序列化程序组,python,django,django-rest-framework,Python,Django,Django Rest Framework,我希望api返回模型中按Account\u type字段分组的Account对象。我想这样做,以便在我的JS代码中更容易访问分组帐户。这是现在返回的内容: [{ "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
Account\u type
字段分组的Account
对象。我想这样做,以便在我的JS代码中更容易访问分组帐户。这是现在返回的内容:
[{
"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"
}]
我希望它能像这样返回:
{
"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"
}
]
}
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.data
def get_savings(self, obj):
return self._build_account_list(Account.SAVINGS)
...
class Meta:
model = Account
fields = ('checking', 'savings', 'credit_card')
型号:
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)
序列化程序:
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('id',
'owner',
'account_name',
'account_type',
'created_time',
'modified_time')
def create(self, validated_data):
account = Account.objects.create(**validated_data)
return account
编辑:添加my views.py,因为我很好奇这是否是问题所在
class AccountViewSet(viewsets.ModelViewSet):
queryset = Account.objects.all().order_by('account_name')
# serializer_class = AccountSerializer
serializer_class = AccountByTypeSerializer
def 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)
由于您只有有限的帐户类型选择,因此可以使用
SerializerMethodField
s,如下所示:
{
"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"
}
]
}
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.data
def get_savings(self, obj):
return self._build_account_list(Account.SAVINGS)
...
class Meta:
model = Account
fields = ('checking', 'savings', 'credit_card')
我建议您使用
信用卡
而不是信用卡
,但如果您真的需要使用后者,只需将覆盖到表示形式
为什么不Model.objects.all().order\u by(“帐户类型”)
在您看来?我的目标是能够在我的UI代码中更轻松地访问这些内容,而不必迭代整个响应。按account\u type
排序确实会收集它们,但这并不能使仅提取特定的account\u type以在UI中呈现变得更容易。为什么不想使用javascript来进行此重塑?从api获取数据后,只需重新整形即可。似乎比创建自定义api端点更干净、更简单。我更愿意在服务器端做这种事情。这是一种糟糕的做法吗?我想我在寻找更有活力的东西。然而,关于有限的选择,你是对的。这份清单将来可能会增加,但我不认为它会变得难以管理。我将尝试一下。添加.distinct()
比如accounts=Account.objects.filter(Account\u type=Account\u type).distinct()
?添加.distinct()
并不能解决重复的问题,可能是我的视图造成的。我已经在原来的帖子中添加了它。这不起作用,因为我在视图中的列表
方法中将many=True
更改为many=False