Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRF: Using ModelForm to validate drf data fails when a MoneyField is present in attrs. #670

Open
zackkh opened this issue Jun 4, 2022 · 0 comments

Comments

@zackkh
Copy link

zackkh commented Jun 4, 2022

Greetings!

I use ModelForm to validate my api data, it works well for serializers without MoneyField, but it breaks on serializers with one.

The error says:

{
    "price": [
        "This field is required."
    ]
}

# Serializer

class FormModelSerializer(serializers.ModelSerializer):

    validate_with_form = True

    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        form = getattr(self.Meta.model, 'form', None)
        setattr(self, 'form_class', form)

    def validate(self, attrs):
        print(attrs)
        # output
        # OrderedDict([('image', None), ('name', 'Shrimp Fried Rice'), ('price', Decimal('69.00')), ('description', ''), ('instructions', ''), ('package', <Package: [2] Wok Box - 8oz>)])
        # Field price is present here ...
        update_money_fields = ['price', 'cost', 'margin',
                               'total', 'paid', 'discount', 'delivery_fee']

        for field in update_money_fields:
            if field in attrs.keys():
                attrs[f'{field}_0'] = attrs[field]

        if self.validate_with_form:
            if hasattr(self, 'form_class'):
                self.form = self.form_class(instance=self.instance, data=attrs)
            else:
                try:
                    self.form = self.Meta.model.form(
                        instance=self.instance, data=attrs)
                except AttributeError:
                    self.form = None

            if self.form is not None:
                if not self.form.is_valid():
                    raise serializers.ValidationError(self.form.errors)

                return attrs

        return super().validate(attrs)

    def save(self, **kwargs):
        if self.form:
            return self.form.save()
        return super().save(**kwargs)


class ProductModelSerializer(FormModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'

# Model
class Product(...):
    package = ForeignKey
    image =ImageField
    price = MoneyField
    description = TextField
    instructions = TextField

    @classproperty
    def form(cls):
        from django import forms
        class ProductForm(forms.ModelForm):
            def clean(self):
                dt = super().clean()
                print(dt)
                # output
                # {'package': <Package: [2] Wok Box - 8oz>, 'image': None, 'name': 'Shrimp Fried Rice', 'description': '', 'instructions': ''} 
                # field price is missing here ...
                
                return dt

            class Meta:
                model = cls
                fields = '__all__'

        return ProductForm

i have tried to pass price_0 for price amount but nothing works.

Version:

django-money                     2.1.1
djangorestframework              3.13.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant