13👍
You could use a subset of the fields in your ModelForm by specifying those fields as follows:
class PartialAuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title')
From the docs:
If you specify fields or exclude when creating a form with ModelForm,
then the fields that are not in the resulting form will not be set by
the form’s save() method.
https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#using-a-subset-of-fields-on-the-form
19👍
Got this figured. What I do is update the request.POST dictionary with values from the instance – so that all unchanged fields are automatically present. This will do it:
from django.forms.models import model_to_dict
from copy import copy
def UPOST(post, obj):
'''Updates request's POST dictionary with values from object, for update purposes'''
post = copy(post)
for k,v in model_to_dict(obj).iteritems():
if k not in post: post[k] = v
return post
and then you just do:
form = CModelForm(UPOST(request.POST,c_instance),instance=c_instance)
- Check if a function has a decorator
- How do you actually use a reusable django app in a project?
- What should be in gitignore, and how do I put env folder to gitignore and is my folder structure correct?
- How to convert a list of dictionaries to JSON in Python / Django?
4👍
I’m surprised nobody mentioned modelform_factory
yet.
You can easily achieve partial form updates by creating a specific version of a form class, defining the subset of fields you’re interested in:
from django.forms import modelform_factory
...
foo = get_object_or_404(Foo, slug=foo_slug)
if request.method == "POST":
PartialFooForm = modelform_factory(
Foo, form=FooForm, fields=("my_first_field", "my_second_field",)
)
form = PartialFooForm(request.POST, instance=foo)
if form.is_valid():
foo = form.save()
return redirect(foo)
else:
form = FooForm(instance=foo)
2👍
Django’s ModelForm
isn’t designed to handle a partial update of an arbitrary subset of fields on the model.
The use case described by the OP, a desktop app hitting an API, would be handled better by Django Rest Framework.
Specifically, you would create a serializer that inherits from ModelSerializer
, and then use it in an UpdateAPIView
. Serializers in DRF are analogous to forms in Django.
If you don’t mind adding another dependency with DRF, which is a really great library, this probably beats rolling your own solution.
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = '__all__'
class MyModelDetail(generics.RetrieveUpdateAPIView):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
- Django rest framework: 'create( )' NotImplementedError when making Http POST request
- How to have a nested inline formset within a form in Django?
- Use a django built in filter in code (outside of a template)
2👍
I know I’m very late to the party, but could you create a factory function for the form.
def model_form_factory(cls, data, *args, **kwargs):
""" Create a form to validate just the fields passed in the data dictionary.
e.g. form = form_factory(MyModel, request.POST, ...)
"""
data = data.copy()
data.pop('csrfmiddlewaretoken', None)
class PartialForm(forms.ModelForm):
class Meta:
model = cls
fields = data.keys()
return PartialForm(data, *args, **kwargs)
- Variable not found. Declare it as envvar or define a default value
- Django logging requests
- Django-allauth, JWT, Oauth
- Method in Django to display all attributes' values belonging to a created object?
1👍
I solved this similar to Roman Semko’s answer (which may not work with ManyToMany fields):
Alter your form’s __init__
method to update the data:
import urllib
from django import forms
from django.http import QueryDict
from django.forms.models import model_to_dict
class MyModelForm (forms.ModelForm):
class Meta:
model = MyModel
def __init__ (self, *args, **kwargs):
super(MyModelForm, self).__init__(*args, **kwargs)
# if form has being submitted and
# model instance exists, then get data
if self.is_bound and self.instance.pk:
# get current model values
modeldict = model_to_dict( instance )
modeldict.update( self.data.dict() )
# add instance values to data
urlencoded = urllib.urlencode( modeldict )
self.data = QueryDict( urlencoded )
- Display query string values in django templates
- Store browser tab specific data
- Why is checking if two passwords match in Django so complicated?
0👍
Well, you must create method to init form with absent data in your request, something like:
class MyModel(Model):
... your model ...
def initial(self,data):
fields = [list of possible fields here]
for field in fields:
if data.get(field) is None:
data[field] = getattr(self,field)
return data
Then, pass this data in your form like:
form = MyForm(instance.initial(request.POST.copy()),instance=instance)
for JSON:
from json import loads
form = MyForm(instance.initial(loads(request.body)),instance=instance)
- Django nginx Refused to display in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'
- Why does Django use tuples for settings and not lists?