Login

PatchModelForm - A ModelForm subclass with the semantics of the PATCH HTTP method

Author:
gnrfan
Posted:
May 26, 2012
Language:
Python
Version:
1.4
Score:
0 (after 0 ratings)

Use this class to partially update one or more fields of a model. Only the fields that are bound to the form via the "data" parameter in the constructor get updated. All automatically generated fields have their "required" attribute set to False.

Example 1:

from django.contrib.auth.models import User

class PatchUserForm(PatchModelForm):
    class Meta:
        model = User

user = User.objects.get(username='old_username')
form = PatchUserForm(data={'username':'new_username'}, instance=user)
form.is_valid()
form.save()

Example 2:

from django.contrib.auth.models import User

class PatchUserForm(PatchModelForm):
    class Meta:
        model = User

user = User.objects.get(pk=35)
form = PatchUserForm(data={'last_name':'Smith', 'is_staff': True}, instance=user)
form.is_valid()
form.save()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from django import forms
from django.core.exceptions import ValidationError  
from django.forms.fields import FileField 

                                                                                
class PatchModelForm(forms.ModelForm):       

    def __init__(self, *args, **kwargs):
        for fieldname in self.base_fields:
            self.base_fields[fieldname].required = False
        self.empty_permited = True
        return super(UpdateModelForm, self).__init__(*args, **kwargs)

    def _clean_fields(self):                                                    
        for name, field in self.fields.items():                                 
            # value_from_datadict() gets the data from the data dictionaries.   
            # Each widget type knows how to retrieve its own data, because some 
            # widgets split data over several HTML fields.                      
            value = field.widget.value_from_datadict(
                self.data, 
                self.files, 
                self.add_prefix(name)
            )
            # this is the key difference with the inherited behavior so fields
            # not present in the bound data do not get updated with None values
            if self.add_prefix(name) not in self.data:
                continue
            try:                                                                
                if isinstance(field, FileField):                                
                    initial = self.initial.get(name, field.initial)             
                    value = field.clean(value, initial)                         
                else:                                                           
                    value = field.clean(value)                                  
                self.cleaned_data[name] = value                                 
                if hasattr(self, 'clean_%s' % name):                            
                    value = getattr(self, 'clean_%s' % name)()                  
                    self.cleaned_data[name] = value                             
            except ValidationError, e:                                          
                self._errors[name] = self.error_class(e.messages)               
                if name in self.cleaned_data:                                   
                    del self.cleaned_data[name]  

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

umbrae (on May 28, 2012):

On line 12 you have UpdateModelForm - I assume that's meant to be PatchModelForm.

#

Please login first before commenting.