Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python DRF:按模型字段的序列化程序组_Python_Django_Django Rest Framework - Fatal编程技术网

Python DRF:按模型字段的序列化程序组

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

我希望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-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