How to dinamically access to a field in django form to change instance

Viewed 47

Using a generic CreateView in Django I'm trying to save only the fields that have been changed by user.

I'm trying to do this in my view:

def form_valid(self, form):
        if form.has_changed():
          
          for field in form:
           

            if field.name in form.changed_data:
            
                continue
                
            else:
               
                form.instance.field=None

In the last line I got this error:

object has no attribute 'field'

Is there a way to dynamically access to each field in the form? so I could change it?

1 Answers

Is there a way to dynamically access to each field in the form. Yes.

form.fields[field_name]

So I could change it? Yes.

form.fields[field_name] = django.forms.Charfield(required=False)

But in your code, probably you want to achieve value of the field:

field_value = form[field_name].value

If you have a data bounded field, you can change also data of form:

form.data(form.add_prefix(field_name)) = new_value 

But this is already wrong approach to change something here.

I can imagine: in your case you don't understand how form / modelform saves the data and therefore you want to do something unnecessary:

Once more time, how ModelForm "saves" the data in DB:

  1. Form validate the data.
  2. Form clean the data.
  3. on form.save(**kwargs) - Form create the instance and:
  • call instance.save() if form.save(commit=True)
  • dont call instance.save() if form.save(commit=False)
  1. Instance saves the data.

Form don't save anything itself, instance.save - There is all what you need.

instance.save(self, force_insert=False, force_update=False, using=None, update_fields=None)

In your case you use CreateView - there all fields should be initiated, you can not UPDATE something, this something not exists yet. You can only avoid empty values, if you want.

def form_valid(self, form):
    if form.has_changed():
        form.cleaned_data = {key:val for key,val in form.cleaned_data.items() if val and key in form.changed_data}
    return super().form_valid(form)

al last: form.instance.field is ridiculous

  • form has fields. You can achieve every field by name.
  • Model class has fields. You can achieve every field by name.
  • instance has attributes or properties. You can achieve every attribute by name.

And right now: what you are really want to do?

Related