2012-04-19 5 views
3

Я пытаюсь обновить некоторые поля ModelForm, эти поля не исправлены. (У меня есть только tutor что autopopulated представлением)Django - ModelForm Обновление динамического поля

Модель:

class Session(models.Model): 
    tutor = models.ForeignKey(User) 
    start_time = models.DateTimeField() 
    end_time = models.DateTimeField() 
    status = models.CharField(max_length=1) 

Форма:

class SessionForm(forms.ModelForm): 
    class Meta: 
    model = Session 
    exclude = ['tutor'] 

Для данной сессии иногда мне нужно обновить только end_time, иногда только start_time & end_time.

Как я могу это сделать в представлении?


Редактировать

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

+0

Когда вы говорите «обновление», что вы имеете в виду? Вы визуализируете все поля формы или только те, которые нужно обновить? – okm

+0

Я визуализирую только те, которые были обновлены. (обновление я имею в виду изменение значения) –

+0

Не могли бы вы взять пример для этого, например, в сценарии использования? Все еще не очень уверен в своей цели. – okm

ответ

8

Я должен был сделать что-то подобное раньше, и хотя это не совсем красиво, оно довольно эффективно. Он включает динамическое создание типа во время выполнения и использование этого типа. Для некоторых документов вы можете увидеть DynamicModels for django.

Здесь мы идем .. ваши требования.

  • Вы хотите, чтобы иметь возможность обновлять модель, используя форму
  • Вы хотите выборочно указать, какие поля должны быть обновлены во время выполнения

Таким образом, некоторый код:

def create_form(model, field_names): 
    # the inner class is the only useful bit of your ModelForm 
    class Meta: 
     pass 
    setattr(Meta, 'model', model) 
    setattr(Meta, 'include', field_names) 
    attrs = {'Meta': Meta} 

    name = 'DynamicForm' 
    baseclasses = (forms.ModelForm,) 
    form = type('DynamicForm', baseclasses, attrs) 
    return form 

def my_awesome_view(request): 
    fields = ['start_time', 'end_time'] 
    form = create_form(Session, fields) 
    # work with your form! 
+0

Мне нравится этот. Что не так? –

+0

Я должен сказать, что это не интуитивно. Я написал комментарий «не очень», когда думал о моей реализации для динамических таблиц. Это выглядит довольно элегантно. –

+0

Почему бы не создать и не вернуть форму? построение с помощью 'type()' полезно для динамической модели, которая имеет динамические поля в 'attrs', в вашем коде' attrs' есть только класс 'Meta'. Так или иначе. – okm

1

Поставьте поле формы, как обнуляемые и с «чистыми» методами можно добавить логику для полого еха:

class SessionForm(forms.ModelForm): 
    def clean_end_date(self): 
     cd = self.cleaned_data 
     if (cd["start_date"] and cd["end_date"]) and cd["end_date"] < cd["start_date"]: 
      raise forms.ValidationError("WTF?!") 
     if not (cd["start_date"] or cd["end_date"]): 
      raise forms.ValidationError("need one date") 
     return cd['end_date'] 

Если вы хотите сп ange, используйте другое значение для оператора return.

Это то, что вам может понадобиться для проверки.

Если вы хотите, вы можете скопировать ПОЛУЧИТЬ словарь в ваших просматривать и обновлять значения перед вашей формой создания экземпляра

def my_view(request): 
    r_data = request.GET.copy() 
    r_data.merge(request.POST) 

    data = dict([(key, my_function(key, value)) for key, value in r_data.iteritems() if key in MyForm.fields]) 
    form = MyForm(data=data) 
    [...] 

надеется, что это поможет.

+0

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

0

Вы можете вызвать конструктор формы как это:

class SessionForm(forms.ModelForm): 
    class Meta: 
     model = Session 
     exclude = ['tutor', 'start_time'] 

    def __init__(self, your_extra_args, *args, **kwargs): 
     super(SessionForm, self).__init__(*args, **kwargs) 
     if need_end_time_start_time(your_extra_args): 
      self.fields['start_time'] = forms.DateTimeField()  

Чтобы использовать этот класс, вы должны передать аргумент «your_extra_args» в форму:

session_form = SessionForm('foo') 
+0

Если у меня есть модель с 10 полями, и каждая из них обновляется независимо, вы имеете в виду, что я должен делать это для каждого? –

+0

В этом случае у вас должно быть правило, для которого нужно обновить право? Дайте вашим 10 полям имя, такое как field_1, field_2, ... и затем вы должны использовать цикл, чтобы сделать это за один шаг. – vutran

+0

или используйте kwargs, вы сможете с setattr легко переводить значения. но я думаю, скопируйте свой запрос/получите запрос dict и измените его в представлении, что может быть хорошим для вас способом, вы сможете производить eterate по полям и вычислять то, что хотите, а затем проверять свою модификацию через форму. – christophe31

0

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

Если я понимаю ваш вопрос, вам нужно создать два разных класса на основе ModelForm, оба этих класса имеют одинаковое значение модели внутри класса Meta. Исключить и включить нужные поля. Итак, теперь у вас есть разные классы ModelForm, которые вы можете вызвать внутри своей логики представления.

С этим вы будете иметь две разные формы, которые зависят от той же модели, с разными полями по умолчанию.

С умным дизайном url и view вы сможете использовать приведенную выше идею для обслуживания нескольких форм из той же модели.

Смежные вопросы