[Answer]-Modify data before creating model instance using django ModelForm

1👍

If I understood correctly, you’d like to attach the Foo instance to Bar,
based on user’s input for the field a, and to automatically create a Foo instance
if one doesn’t already exist.

With these models:

class Foo(model.Model):
    a = model.CharField()

class Bar(model.Model):
    b = model.ForeignKey(Foo)
    ... more fields here

in your ModelForm you can do this:

class BarForm(forms.ModelForm):
    class Meta:
        model = Bar
        fields = [other fields from the Bar model, ...]

    foo_a = forms.CharField(...)

    foo_instance = None  # for clarity/documentation only

    def clean_foo_a(self):
        value = self.cleaned_data['foo_a']
        self.foo_instance = Foo.objects.get_or_create(a=value)
        return value

    def save(self, *args, **kwargs):
        """
        Attach Foo to the newly created Bar instance.
        The code below takes into account the standard "commit" kwarg for ModelForm's
        """
        commit = kwargs.pop('commit', True)
        bar_instance = super(BarForm, self).save(commit=False, *args, **kwargs)
        bar_instance.b = self.foo_instance
        if commit:
            bar_instance.save()
        return bar_instance

The idea is to add another field – foo_a – that we’ll use to lookup/create the Foo instance.

Other possibilities include custom widgets that do this for you, custom form fields, etc.,
but it all depends on how often will you use this pattern in your app.

Leave a comment