Please make save_instance and construct_instance methods of ModelForm
|Reported by:||gcc||Owned by:||nobody|
|Has patch:||no||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
I want to use ModelForm and Generic Class-based Views to create records for an ordering/payment system (so security is important). I want to set the user field of the created record to the current logged-in user, without any way for them to override it.
I asked the best way to do this on Stack Overflow, and I didn't get any satisfactory (non-ugly) answers of how to do this. The essential problem is that:
- CBVs have access to the request, but not the instance;
- ModelForm has no access to the request (but can be given it) and only has access to the model after it's been instantiated;
- Model has no access to the request, and its attributes are magical.
The closest to a "nice" solution was the only answer I got so far: construct the ModelForm passing in the request, and modify the object before saving it. However ModelForm has no access to the object until it's saved, unless it does a save(commit=False) and then saves the object and its m2m relations, which is also ugly.
The save_instance function is not a method of ModelForm, but it does poke a new method into the ModelForm which called it, and that's pretty ugly too:
else: # We're not committing. Add a method to the form to allow deferred # saving of m2m data. form.save_m2m = save_m2m
I propose making save_instance and construct_instance methods of ModelForm, instead of stand-alone functions that do black magic on a ModelForm. This way, I could override construct_instance to modify the instance before it's saved, setting its user member to the one in the request that I saved earlier, and that's the cleanest approach that I've seen so far (minimal code, minimal magic).