DRF 中 ModelSerializer 中创建和更新方法中的重复代码

Duplicated code in create and update methods inside ModelSerializer in DRF

我创建了一个 ModelSerializer,我在其中覆盖了默认的创建和更新方法,发现代码几乎相同。它负责保存图像(通过 FK 连接)和匹配 PaymentMethods(通过 M2M 连接)以创建和替换 Images 和 PaymentMethods 在更新的情况下,但主要验证和创建逻辑是相同的。有什么办法可以缩短这个吗?到目前为止,我还没有找到任何关于这种可能性的资源。

class TruckSerializer(serializers.ModelSerializer):
    location = LocationSerializer(read_only=True,)
    owner = serializers.PrimaryKeyRelatedField(read_only=True,)

    class Meta:
        model = Truck
        fields = "__all__"

    def create(self, validated_data):
        data = self.context.get("view").request.data
        if data.get("payment"):
            new_payments = []
            payments = data.get("payment")
            for payment in payments.split(", "):
                try:
                    filtered_payment = PaymentMethod.objects.get(
                        payment_name__iexact=payment).id
                except PaymentMethod.DoesNotExist:
                    raise serializers.ValidationError(
                        'Given payment method does not match')
                new_payments.append(filtered_payment)
        truck = Truck.objects.create(**validated_data)              <---- valid only in create
        truck.payment_methods.add(*new_payments)
        if data.get("image"):
            for image_data in data.getlist("image"):
                TruckImage.objects.create(truck=truck, image=image_data)
        return truck

    def update(self, instance, validated_data):
        data = self.context.get("view").request.data
        if data.get("payment"):
            new_payments = []
            payments = data.get("payment")
            for payment in payments.split(", "):
                try:
                    filtered_payment = PaymentMethod.objects.get(
                        payment_name__iexact=payment).id
                except PaymentMethod.DoesNotExist:
                    raise serializers.ValidationError(
                        'Given payment method does not match')
                new_payments.append(filtered_payment)
        instance.payment_methods.clear()                            <---- valid only in update
        instance.payment_methods.add(*new_payments)
        if data.get("image"):
            images = instance.images.all()
            if images.exists():                                     <---- valid only in update
                instance.images.all().delete()
            for image_data in data.getlist("image"):
                TruckImage.objects.create(truck=instance, image=image_data)
        return super(TruckSerializer, self).update(instance, validated_data)

您可以定义一个新方法来处理您的重复代码。引入新方法后,您的 class 现在看起来像这样。


class TruckSerializer(serializers.ModelSerializer):
    # your existing code....

    def get_new_payments(self):
        data = self.context.get("view").request.data
        if data.get("payment"):
            new_payments = []
            payments = data.get("payment")
            for payment in payments.split(", "):
                try:
                    filtered_payment = PaymentMethod.objects.get(
                        payment_name__iexact=payment).id
                except PaymentMethod.DoesNotExist:
                    raise serializers.ValidationError(
                        'Given payment method does not match')
                new_payments.append(filtered_payment)
            return new_payments

    def create(self, validated_data):
        new_payments = self.get_new_payments()  # will return new_payments
        truck = Truck.objects.create(**validated_data)
        truck.payment_methods.add(*new_payments)
        if data.get("image"):
            for image_data in data.getlist("image"):
                TruckImage.objects.create(truck=truck, image=image_data)
        return truck

    def update(self, instance, validated_data):
        new_payments = self.get_new_payments()  # will return new_payments
        instance.payment_methods.clear()
        instance.payment_methods.add(*new_payments)
        if data.get("image"):
            images = instance.images.all()
            if images.exists():                                  
                instance.images.all().delete()
            for image_data in data.getlist("image"):
                TruckImage.objects.create(truck=instance, image=image_data)
        return super(TruckSerializer, self).update(instance, validated_data)