1👍
You can do that by overriding the __init__()
method of FooForm
.
We override the __init__()
method and check if instance
argument was passed to the form. If instance
was passed, we disable the root
and leaf
form fields so that it is not displayed in the template.
We will pass instance
argument to the form when the request is of type foo/create/4
i.e. leaf_id
is not None
.
forms.py
class FooForm(ModelForm):
def __init__(self, *args, **kwargs):
super(FooForm, self).__init__(*args, **kwargs) # call the 'super()' init method
instance = getattr(self, 'instance', None) # get the `instance` form attribute
if instance and instance.id: # check if form has 'instance' attribute set and 'instance' has an id
self.fields['root'].widget.attrs['disabled'] = 'disabled' # disable the 'root' form field
self.fields['leaf'].widget.attrs['disabled'] = 'disabled' # disable the 'leaf' form field
# custom validation functions here
....
class Meta:
model = Foo
fields = '__all__'
In our view, we first check if leaf_id
argument was passed to this view. If leaf_id
was passed,we retrieve the Foo
object having leaf id as the leaf_id
. This instance
is then passed when initializing a form and is updated when form.save()
is called. We will use the instance
to populate the form with values as the attributes set on the instance
.
If leaf_id
is not passed, then we initialize FooForm
with data
argument.
views.py
def create(request, leaf_id=None):
# Get the instance if any
instance = None
if leaf_id:
instance = Foo.objects.get(leaf_id=leaf_id) # get the 'Foo' instance from leaf_id
# POST request handling
if request.method=='POST':
if instance:
form = FooForm(data=request.POST, instance=instance) # Populate the form with initial data and supply the 'instance' to be used in 'form.save()'
else:
form = FooForm(data=request.POST)
if form.is_valid():
new = form.save()
return redirect('show.html', root_id=new.root.id)
return render('create_foo.html',
{ 'form': form })
# GET request handling
if instance:
form = FooForm(initial=instance._data, instance=instance) # form will be populated with instance data
else:
form = FooForm() # blank form is initialized
return render('create_foo.html',
{ 'form': form })