I have a modelform which has a user_id field that I have excluded from the form. This form is made into a modelformset. The reason I have the user field excluded is because it's not an editable value. I don't want that value to go to the HTML form where it can be tampered with by naughty user.
When I try to save this model formset, I get an error saying user_id can't be null. I need someway to add request.user to each form before I save that formset in the view. How can I do this? I know how to add the value to a single instance of a modelform, but I can't figure out how to do it with a formset.
If you are not passing request.user to form, there is no direct way that you can get it in form's save method.
However there is a way, if you want user to be available directly at form's save method, from outside the context. Check out, http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser .
When you are saving formset remeber to:
if formset.is_valid():
instances = formset.save(commit=False)
for instance in instances:
instance.user_id = request.user.id
instance.save()
You no need anything else. BTW I dont't understand why save user id not user object ?
Related
What is the best procedure in Django for saving a form related to another model without the use of inline formsets?
Problem setup:
Model Address is related by a foreign key to Model User
Each User can have multiple Addresses. I want to add a new address to an User.
views.py
In the AddAddress class (extending CreateView) the form.errors has the error
{'user': ['This field is required.']}
The user pk is in the url /address/add/<int:pk>
First, as Daniel Roseman noted, have to make sure the field "user" does not exist in the fields list of the form. This will make sure that the form is valid.
Override the form_valid method in the view class to save the form without commiting, then setting the required user to the resulting instance and then invoking the save directly on the it.
def form_valid(self, form):
address_obj = form.save(False)
address_obj.user = User.objects.get(pk=self.kwargs['pk'])
return HttpResponseRedirect(self.get_success_url())
I have a ModelForm which has a subset of fields of the model it is for. When I'm processing that form, checking is_valid etc, I want to check the value of a given field that may have changed, so I check if form.has_changed() and then I check if myfield in form.changed_data. If that is true, I want to set the value for a field on my model, but that field is NOT on this modelform. How might I go about doing that?
I know I can access myform.instance directly, but since I'm already calling myform.save() later on, can I set the value on the form itself somehow, even if that field is not part of the modelform?
Use commit=False in ModelForm.save, like this:
instance = form.save(commit=False)
if requires_update:
instance.field_to_change = value_to_set
instance.save()
I have a couple of forms, one is created from as a ModelForm and the other is a simple Form. Both of them are used in a request.POST, and to obtain the information from them I am using to different methods:
For the ModelForm form, I do this:
form = ApplicantForm(request.POST)
if form.is_valid():
applicant = form.save(commit=False)
applicant.confirmation_code = '999999'
applicant.save()
For the simple form, I am using:
form = ConfirmationCode(request.POST)
code = request.POST['confirmation_code']
confirmation_id=request.POST['confirmation_id']
As you can see, to access the information in the first form I am using the "form.save.ANYFIELD", and for the second one I am using "request.POST['ANYFIELD']. Is it possible to access the the information in the first form using the request.POST methods even if it hasnt been saved? Which is better?
You can try like this for modelform:
form = ApplicantForm(request.POST)
if form.is_valid():
app_code= form.cleaned_data['confirmation_code'] #assuming confirmation_code is a field in your modelform
.....
You seem a bit confused about what saving is doing in a modelform. When you call form.save(), you're creating a new instance of the model the form is associated with, and (unless you specify commit=False) saving that data to the database. Because you have an instance, you can use any of the normal model instance methods and access patterns.
If you want to use a form without an associated model, you can't call save - because there's nothing to save, and no model to create an instance of - but you should access the data via the form.cleaned_data dictionary after you call form.is_valid(). This is because the data in cleaned_data has been validated according to the rules in the form, and converted into the relevant types where necessary: for instance, if you had an IntegerField in your form called my_number, request.POST['my_number'] will be a string like "3" but form.cleaned_data['my_number'] will be an actual integer, 3.
One of the custom fields of my ModelForm holds the pk for the database row to be edited. Therefore, I would like to first check if the form is valid, then set the instance using the cleaned pk field, then save the form. Is it even possible?
My workaround right now is to create a new ModelForm instance, which is not very neat.
If your form is overwriting all the information in the instance, you could simply set the primary key manually:
if form.is_valid():
obj = form.save(commit=False)
obj.pk = form.cleaned_data['pk_to_edit']
obj.save()
return ...
I have created multiple sub-forms from one model to use the FormWizard in Django.
Confusing is the saving part. Once the user finished the form, I wanted to save the information in the DB. This is fairly simply with one form, where I can say
one_form_from_model.save()
But could I do it when I get a form_list returned. I read some postings but they did not make any sense to me.
Can I clean the data
form.cleaned_data for form in form_list]
and then go through every form? But then I would need to know in which form I am to find the right fields. Isn´t there any easier way to do it?
Thank you for your advice!
Try something like this:
instance = MyModel()
for form in form_list:
for field, value in form.cleaned_data.iteritems():
setattr(instance, field, value)
instance.save()