DRF:序列化器按模型分组

时间:2019-07-29 19:18:11

标签: python django django-rest-framework

我希望我的api返回由模型中的Account字段分组的account_type对象。我想这样做,以便在我的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 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

编辑:添加我的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)

1 个答案:

答案 0 :(得分:2)

由于帐户类型选择的数量有限,因此可以使用SerializerMethodField,如下所示:

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')

我建议您使用credit_card代替credit card,但是如果您确实需要使用后者,只需覆盖to_representation