python-3.x 在模型序列化程序创建方法中创建多个对象

ymzxtsji  于 2023-11-20  发布在  Python
关注(0)|答案(1)|浏览(144)

我需要下面的DRF API视图来在我的Django项目中列出并创建Withdraw记录。

class WithdrawListCreateAPIView(PartnerAware, WithdrawQuerySetViewMixin, generics.ListCreateAPIView):
    permission_classes = (TokenMatchesOASRequirements,)
    required_alternate_scopes = {
        "GET": [[OTCScopes.WITHDRAW_READ]],
        "POST": [[OTCScopes.WITHDRAW_CREATE]],
    }

    def get_serializer_class(self, *args, **kwargs):
        if self.request.method == "POST":
            return WithdrawCreateSerializer
        return WithdrawSerializer

    def initial(self, request, *args, **kwargs):
        super().initial(request, *args, **kwargs)
        self.get_partner_info()

    def perform_create(self, serializer):
        serializer.save(partner=self.partner, created_by=self.request.user)

字符串
我的API构造必须是针对单个记录的,但是这个量可能大于一个称为SETTLEMENT_MAX_AMOUNT的特定量,我必须将其分解为多个Withdraw记录,并且我必须为每个记录创建一个单独的记录,我应该将所有这些在一个列表中创建的记录返回给用户。下面是我为这种情况实现的相关序列化器:

class WithdrawCreateSerializer(serializers.ModelSerializer):
    target_uuid = serializers.UUIDField(write_only=True)

    def validate_target_uuid(self, value):
        partner = self.context["view"].partner
        try:
            target = WithdrawTarget.objects.get(active=True, uuid=value, partner=partner)
        except WithdrawTarget.DoesNotExist:
            raise serializers.ValidationError("Target does not exist for the current partner.")
        return target.uuid

    def create(self, validated_data):
        target_uuid = validated_data.pop("target_uuid")
        partner = self.context["view"].partner
        target = WithdrawTarget.objects.get(uuid=target_uuid, partner=partner)

        amount = validated_data["amount"]
        num_withdrawals = amount // SETTLEMENT_MAX_AMOUNT
        remaining_amount = amount % SETTLEMENT_MAX_AMOUNT

        withdrawals = []
        for _ in range(num_withdrawals):
            withdraw_data = {
                "target": target,
                "amount": SETTLEMENT_MAX_AMOUNT,
                "partner": validated_data["partner"],
                "created_by": validated_data["created_by"],
                "description": validated_data.get("description"),
            }
            withdrawal = Withdraw.objects.create(**withdraw_data)
            withdrawals.append(withdrawal)

        if remaining_amount > 0:
            withdraw_data = {
                "target": target,
                "amount": remaining_amount,
                "partner": validated_data["partner"],
                "created_by": validated_data["created_by"],
                "description": validated_data.get("description"),
            }
            withdrawal = Withdraw.objects.create(**withdraw_data)
            withdrawals.append(withdrawal)

        return withdrawals

    class Meta:
        model = Withdraw
        fields = ("uuid",
                  "amount",
                  "target_uuid",
                  "description",
                  "status",
                  "tracker_id",
                  "created_at",)
        extra_kwargs = {
            "amount": {"required": True, "allow_null": False},
            "target_uuid": {"required": True, "allow_null": False},
        }
        read_only_fields = ("state", "tracker_id", "created_at")


现在通过发送此请求:

curl --location '127.0.0.1:8000/withdraws/' \
--header 'Authorization: Bearer blob' \
--form 'amount="2240"' \
--form 'target_uuid="d4d92a38-4193-443c-b11e-8022e64543a4"'


例如,SETTLEMENT_MAX_AMOUNT的值是1000,通过上面的请求,我应该得到3条“提款”记录,金额为:1000,1000,240。
我收到以下错误响应:

AttributeError at /withdraws/
Got AttributeError when attempting to get a value for field `amount` on serializer `WithdrawCreateSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `list` instance.

The original exception text was: 'list' object has no attribute 'amount'.


我怎样才能改变上面的视图或序列化程序,使系统按照我想要的方式运行?

z9smfwbn

z9smfwbn1#

通过将我的API视图更改为下面的视图,我解决了这个问题:

class WithdrawListCreateAPIView(PartnerAware, WithdrawQuerySetViewMixin, generics.ListCreateAPIView):
    permission_classes = (TokenMatchesOASRequirements,)
    required_alternate_scopes = {
        "GET": [[OTCScopes.WITHDRAW_READ]],
        "POST": [[OTCScopes.WITHDRAW_CREATE]],
    }

    def get_serializer_class(self, *args, **kwargs):
        if self.request.method == "POST":
            return WithdrawCreateSerializer
        return WithdrawSerializer

    def initial(self, request, *args, **kwargs):
        super().initial(request, *args, **kwargs)
        self.get_partner_info()

    def perform_create(self, serializer):
        return serializer.save(partner=self.partner, created_by=self.request.user)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        withdraws = self.perform_create(serializer)
        return Response(WithdrawSerializer(withdraws, many=True).data, status=status.HTTP_201_CREATED)

字符串

相关问题