Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
324 views
in Technique[技术] by (71.8m points)

django - Duplicated code in create and update methods inside ModelSerializer in DRF

I have created a ModelSerializer where I override default create and update methods and found the code to be pretty much the same. It is responsible for saving Images (connected via FK) and matching PaymentMethods (connected via M2M) in case of creating and replace Images and PaymentMethods in case of updating but the main validation and creation logic is the same. Is there any way to shorten this? I haven't found so far any resources for this possibility.

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)
question from:https://stackoverflow.com/questions/65843985/duplicated-code-in-create-and-update-methods-inside-modelserializer-in-drf

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can define a new method that will take care of your duplicate code. After introducing a new method your class now looks like this.


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)



与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...