fildred13
fildred13

Reputation: 2350

Django ModelForm 'instance' param not working as expected

I am using Django's forms to validate API PATCH requests. In the "view" (which I use in quotes because it isn't really a view directly, it is a restless Resource, but that should be irrelevant here) which handles this patch request, self.data contains a dictionary of changes to some of the fields of the License object. I want to instantiate a ModelForm with the instance of the object to be changed. Clearly, though, I am misunderstanding how this works. See below:

def handle_patch(self, pk):
    license = License.objects.get(id=pk)

    form = LicenseResourceForm(self.data, instance=license)

    if not form.is_valid():
        print(form.errors)

If I pass a few fields as data to the above function, form.errors complains about every other required field of the License model, meaning I'm clearly not understanding how setting an instance on a ModelForm works.

I added a few debug prints to Django's ModelForm code itself in the clean() method, and as it begins to do the cleaning process, I can see that self.instance is populated with the instance of License that I expect, which confuses me - the ModelForm object knows the instance, but isn't using it to "fill in the blanks" so to speak.

So what am I misunderstanding? I must be doing this wrong.

EDIT I realize that some of you may want to see the LicenseResourceForm itself, so here it is, including my debug print:

class LicenseResourceForm(ModelForm):
    """Form for License Resource create and change endpoints."""
    class Meta(object):
        model = License
        fields = ['customer', 'service', 'enabled', 'not_valid_before', 'not_valid_after']

    def clean(self):
        try:
            print(self.instance)
            super().clean()
        except Exception as e:
            print(e)

Upvotes: 0

Views: 202

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599490

Django forms aren't meant for API use and don't understand PATCH semantics. They are meant for the workflow of a user entering or changing data in a web form, which will always post all the data to the backend. Therefore, all fields listed in the fields attribute of the form will be checked against the data, and any missing fields will be validated as blank.

You could probably fix this by doing something clever to dynamically set the list of fields based on the data supplied, but really you should use the appropriate tool for validating your data. I don't know restless, but django-rest-framework has serializers which can be used for this.

Upvotes: 1

Related Questions