Как динамически получить доступ к полю в форме django для изменения экземпляра

Используя общий CreateView в Django, я пытаюсь сохранить только те поля, которые были изменены пользователем.

Я пытаюсь сделать это в своем представлении:

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

В последней строке я получил эту ошибку:

у объекта нет атрибута 'field'

Есть ли способ динамического доступа к каждому полю в форме, чтобы я мог изменить его?

Есть ли способ динамического доступа к каждому полю в форме. Да.

form.fields[field_name]

Значит, я могу его изменить? Да.

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

Но в вашем коде, вероятно, вы хотите добиться значения поля:

field_value = form[field_name].value

Если у вас есть поле, ограниченное данными, вы можете изменить также данные формы:

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

Но это уже неправильный подход, чтобы что-то здесь изменить.

Я могу представить: в вашем случае вы не понимаете, как форма / modelform сохраняет данные, и поэтому хотите сделать что-то ненужное:

Еще раз, как ModelForm "сохраняет" данные в БД:

  1. Форма проверки данных.
  2. Форма очищает данные.
  3. on form.save(**kwargs) - Форма создает экземпляр и:
  • вызвать instance.save(), если form.save(commit=True)
  • не вызывать instance.save(), если form.save(commit=False)
  1. Инстанция сохраняет данные.

Форма сама ничего не сохраняет, instance.save - Там есть все, что вам нужно.

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

В вашем случае вы используете CreateView - там все поля должны быть инициированы, вы не можете UPDATE что-то, это что-то еще не существует. Вы можете только избегать пустых значений, если хотите.

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

последний: form.instance.field смешно

  • form имеет поля. Вы можете достичь каждого field по имени.
  • Model class имеет поля. Вы можете достичь каждого field по имени.
  • instance имеет атрибуты или свойства. Вы можете достичь каждого attribute по имени.

А прямо сейчас: что вы действительно хотите сделать?

Я пытаюсь обновить объекты в Модели, но не напрямую за один шаг. Мне нужно, чтобы когда пользователь хочет обновить объект, он мог предложить некоторые изменения, но перед обновлением объекта другой пользователь должен одобрить его предложения перед сохранением изменений.

Поскольку модель имеет много полей и изменения могут затронуть только те поля, которые были отредактированы, я хочу изменять только отредактированные поля.

Наверное, это не лучший подход, но вот что я сделал:

Я создал вторую модель, чтобы сохранить предложения по изменению, поэтому у меня есть две модели, выглядящие почти одинаково:

class MainModel(models.Model):
    name= models.CharField(max_length=100)
    field_1= models.CharField(null=True,blank=True, max_length=200)
    field_2= models.CharField(max_length=100)
    field_3= models.CharField(max_length=100)
    ...
    field_n = bla bla bla

class SuggestionsModel(models.Model):
    
    name= models.Foreingkey(MainModel, on_delete=models.CASCADE)
    field_1= models.CharField(null=True,blank=True, max_length=200)
    field_2= models.CharField(null=True,blank=True, max_length=200)
    field_3= models.CharField(null=True,blank=True, max_length=200)
    ...
    field_n = bla bla bla

    suggested_by = models.Foreingkey(User, on_delete=models.CASCADE)
    approved= models.BooleanField(default=False)
    checked= models.BooleanField(default=False)

и в представлениях я получил поле "одобрено" в форме, если пользователь выбрал "True", я обращаюсь к каждому полю в MainModel и проверяю, содержит ли предложение какие-либо изменения, если да, я изменяю его в MainModel. Наконец, я обновляю модель SuggestionsModel.

Я все еще работаю над этим. На данный момент у меня есть что-то вроде этого в UpdateView:

def form_valid(self,form):
    
    clean=form.clean()
    
    object_to_update=clean.get('name')
    approved= clean.get('approved')
    
    if approved==False:

        #I update the suggestion as checked and that's it.


     else:

        #the suggestion was approved, so changes should be updated in MainModel:

    fields=MainModel._meta.fields #I get a list of fields in MainModel

    for field in fields:
        
        changed = clean.get(field.name) # I check if the field named campo.name has being changed or not
        
                   
        if changed == None:
            continue

         else:

            #code to update the MainModel with user's approved suggestions
            # I create a dictionary with all the changes before updating so I hit the db only once.

         #after all this, I can say form.is_valid and update the suggestion as approved.

Как я уже говорил, возможно, есть лучшие способы сделать это, но этот работает.

Спасибо

Вернуться на верх