Django – Actualización de campo dynamic de ModelForm

Estoy tratando de actualizar ciertos campos a ModelForm, estos campos no son fijos. (Solo tengo un tutor que es autopopulado por la vista)

Modelo:

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

Formar:

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

Para una sesión determinada a veces necesito actualizar solo end_time , a veces solo start_time y end_time .

¿Cómo puedo hacer eso en una vista?


Editar

He dado ejemplos, pero no se limita a estos ejemplos, los campos que necesito actualizar no están predefinidos, necesito poder actualizar cualquier campo (s)

He tenido que hacer algo similar antes, y aunque no es exactamente bonito, es bastante efectivo. Implica crear dinámicamente un tipo en tiempo de ejecución y usar ese tipo. Para algunos documentos, puedes ver DynamicModels para django.

Aquí vamos … sus requerimientos.

  • Quieres poder actualizar un modelo utilizando un formulario.
  • Desea especificar de forma selectiva qué campos se actualizarán en tiempo de ejecución

Entonces, algún código:

 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! 

Ponga sus campos de formulario como anulables y con métodos “limpios” puede agregar lógica a los campos ej:

 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'] 

Si desea cambiar el valor, use un valor diferente a la statement de retorno.

Esto es lo que puede necesitar para la validación.

Si lo desea, puede copiar el diccionario GET en su vista y actualizar los valores antes de crear su formulario.

 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) [...] 

espera que ayude.

Puedes invocar el constructor de formularios de esta manera:

 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() 

Para usar esta clase, debe pasar un argumento “your_extra_args” a su formulario:

 session_form = SessionForm('foo') 

Su pregunta sugiere que tiene un requisito que utiliza el mismo modelo pero diferentes campos están ocultos en su ModelForm, según sus necesidades.

Si entiendo su pregunta, entonces necesita crear dos clases diferentes basadas en ModelForm, estas dos clases tienen el mismo valor de modelo dentro de la clase Meta. Excluye e incluye los campos que necesites. Así que ahora tiene diferentes clases de ModelForm a las que puede llamar dentro de su lógica de vista.

Con esto tendrás dos formas diferentes que dependen del mismo modelo, con diferentes campos predeterminados.

Con una url inteligente y un diseño de vista, podrá utilizar la idea anterior para servir múltiples formularios desde el mismo modelo.