how can i improve my approach on closing of a save form?

First, regarding your override of get_initial: You need to call the parent method with super(), and you need to return the object you get from that call:

def get_initial(self):
    initial = super().get_initial()

    initial['remark'] = testnote

    return initial

It’s also possible that you are misunderstanding the purpose of the initial dictionary: it is generally used to pre-populate the form with data. The keys need to correspond to fields in the form, and the values you assign them will appear in the form (pre-populated) when the user sees the form. They can then use that value, or type in a new one.

Second, your approach to overriding form_valid looks misguided to me, unless I’m misunderstanding your purpose. The object you create with the call to self.object = form.save() is a different object than the one you are creating with your call to .create(). You are then giving the 2nd object the ‘name’ from the first one. But this should all be one step of creation, not two mostly unrelated steps, which is what you’re doing now. In other words, the call to create() is redundant, since the whole point of form.save() is to create an object. I can see that this is why you used commit=False, so the database is only updated on the call to create(). But you can avoid this redundancy and still achieve what you are trying to do. One way is to call save() twice:

self.object = form.save(commit=False)   # create python object but do not update the database yet
self.object.some_field = some_value     # modify the new object
self.object.save()       # save the object, updating the database

Since you mentioned not being able to access the form fields, it’s possible that something like this is what you were actually intending to do:

def form_valid(self, form):
    
    form.instance.name = some_name_string
    form.instance.price = 99
    
    return super().form_valid(form) #call to super() saves the form

As you see above, you can access the fields of the form using .instance.field-name. This is generally used to assign values to fields that were left out of the form — things you don’t want the user to provide input for. You need to do this before the form is submitted, of course: you are basically manually updating values in the model that will be created, and then it gets saved by the call to super() in the return statement. If you need even more control over what’s going on in this method, you could use self.object = form.save() as you had in your original code, placed after the ‘instance’ usage above, and then end with a redirect instead of the call to super():

def form_valid(self, form):
    
    form.instance.name = some_name_string
    form.instance.price = 99

    self.object = form.save()

    # perform other tasks as needed here, and with access to self.object, the
    # newly created object resulting from saving the form above.
    
    return redirect(self.get_success_url())  # import the redirect shortcut, it's cleaner

As you can see, there are many ways to override the form_valid method of the generic editing views. The approach taken usually depends on the desired order of events between three main tasks: submitting/saving the form (and thereby its object, thanks to ModelForm), performing ‘extra’ work as needed, and redirecting. The redirect is always last of course, but you can shift around the first two as needed, which you are already doing.

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top