2012-07-29 16 views
17

Desde el código fuente, puede ver que la clase Form de Django 1.4 tiene un método has_changed() y una propiedad changed_data que parecen bastante útiles, pero no están documentadas. Mi pregunta es: hacer estos trabajos como se esperaba, es decir:En Django 1.4, ¿Form.has_changed() y Form.changed_data, que no están documentados, funcionan como se esperaba?

  • En Form.clean(), Form.has_changed() vuelve True si los hay ningún formulario de datos ha cambiado, de lo contrario False
  • En Form.clean(), Form.changed_data es una lista de nombres de campos cuyos valores tienen cambiado

En caso afirmativo, ¿hay algún motivo específico para no utilizarlos, aparte de las advertencias/peligros habituales sobre el uso de funciones no documentadas (es decir, sujeto a cambios, no admitidos, etc.)?

NOTA 1: Para que estos widgets personalizados funcionen, dichos widgets deben tener un método _has_changed(), que se define para los widgets integrados.

NOTA 2: Curiosamente, la documentación sí incluye una mención de improviso del método Formset.has_changed(), pero no de Form.has_changed().

+1

gran característica. Gracias por la explicación. ;-) – Houman

Respuesta

23

Después de estudiar la fuente de Django aún más, con consejos útiles de respuesta de Florian, Puedo informar que has_changed y changed_data funcionan como se describe en mi pregunta mientras que el formulario tiene una forma de obtener los datos iniciales para comparar los nuevos datos.

Entonces, la pregunta es, ¿cómo sabe un formulario creado a partir de datos POST cuáles eran los valores iniciales del formulario GET? La respuesta corta es que no, a menos que usted lo diga de alguna manera. Hay dos maneras de saber que:

  1. mediante el argumento initial palabra clave a la forma y/o los initial argumentos clave a los campos, exactamente de la misma manera le dice al obtener el formulario los valores iniciales. NOTA: Si hace esto, depende de usted asegurarse de usar los mismos valores para sus formularios GET y POST. Esta es la única forma verdaderamente confiable de hacerlo, ya que usted controla directamente cuáles son los valores iniciales.

  2. Deje que Django haga el trabajo de recordar los valores iniciales de su GET estableciendo el argumento de palabra clave show_hidden_initial en para cada campo aplicable. Para estos campos, Django representa un elemento de entrada oculto con el valor inicial en el HTML del formulario GET. Más adelante, cuando llame al has_changed o changed_data en el formulario POST, para cualquier campo con show_hidden_initial como True, Django obtendrá automáticamente los valores iniciales de los elementos de entrada ocultos en los datos POST (reemplazando cualquier valor inicial del formulario initial o argumentos de campo).NOTA: al igual que con cualquier cosa que dependa de los datos POST, este enfoque es, en última instancia, poco confiable, ya que los valores para las entradas ocultas aún se pueden cambiar a pesar de estar ocultos.

+1

Cualquier posibilidad de ampliar la forma de usar la palabra clave 'initial'. ¿Lo usas cuando envías el formulario o lo usas cuando vuelve el formulario? ¿Y cómo funciona con 'instance'? – Sevenearths

+1

@ Ghopper21 ¿podría proporcionar un fragmento de código? – andi

5

Usted puede confiar en los métodos de dos condiciones:

  1. que pase el dict de datos inicial a la forma del constructor durante la post solicitudes también.
  2. No utiliza campos con show_hidden_initial=True. (El problema con este tipo de campos es que un usuario puede enviar el valor inicial utilizado para la comparación también y, como tal, no sería digno de confianza.)
+0

gracias! Esta respuesta me plantea otra pregunta: ¿qué es 'show_hidden_initial'? No puedo encontrarlo en los documentos de Django ... – Ghopper21

+0

'show_hidden_initial' solo significa que se genera un segundo campo oculto junto con la salida html original que contiene el valor inicial del campo. –

+0

Ya veo, gracias. – Ghopper21

0

Aquí hay un fragmento de código que hace lo que @ Ghopper21 está sugiriendo. Para obtener los datos iniciales, uso la función values ​​() en QueryDict. Devuelve un diccionario que contiene los datos que pertenecen al objeto. Una advertencia importante es que no he comprobado cómo maneja las referencias de claves externas.

saveStudentView(request,studentID): 
    existingData = Student.objects.filter(id=paperID).values()[0] 
    form = StudentForm(request.POST) 
    if form.is_valid(): 
     form = StudentForm(request.POST, initial=existingData) 
     if not form.has_changed(): 
      //Tell the user nothing has changed 
     else: 
      //Do other stuff 
Cuestiones relacionadas