with tutorial form example data create python django code-reuse

python - example - forms in django tutorial



¿Existe una biblioteca para evitar el envío de formularios duplicados para django? (5)

La respuesta de Kristian Damian es realmente una gran sugerencia. Acabo de pensar en una ligera variación en ese tema, pero podría tener más gastos generales.

Puede intentar implementar algo que se usa en django-piston para objetos BaseHandler , que es un método llamado exists() que verifica si lo que está enviando ya está en la base de datos.

Desde handler.py (BaseHandler):

def exists(self, **kwargs): if not self.has_model(): raise NotImplementedError try: self.model.objects.get(**kwargs) return True except self.model.DoesNotExist: return False

Así que digamos que hace que una función llamada request_exists() , en lugar de un método:

if form.is_valid() if request_exists(request): # gracefully reject dupe submission else: # do stuff to save the request ... # and ALWAYS redirect after a POST!! return HttpResponseRedirect(''/thanks/'')

Estoy tratando de encontrar una manera de evitar que los usuarios envíen dos veces mis formularios. Tengo un javascript que deshabilita el botón de envío, pero todavía hay un usuario ocasional que encuentra una forma de enviar doble.

Tengo una visión de una biblioteca reutilizable que podría crear para protegerla de esto.

En mi biblioteca ideal, el bloque de código se vería así:

try: with acquire_lock({''field1'':''abc'', ''field2'':''def''}) as lock: response = #do some credit card processing lock.response = response except SubmissionWasDuplicate, e: response = e.response

La mesa de bloqueo se vería algo así:

duplicate_submission_locks

  • submit_hash # un MD5 de los argumentos enviados
  • respuesta # datos en escabeche
  • created_at # usado para barrer esta tabla
  • lock_expired # boolean significa que el bloqueo ha caducado

¿Alguien sabe si esto ya existe? No parece difícil escribir, así que si no existe, puedo escribirlo yo mismo.


Para ser honesto, su mejor apuesta (fácil y buena práctica) es emitir un HTTPRedirect () a la página de agradecimiento, y si la página de agradecimiento es la misma que la del formulario, está bien. Todavía puedes hacer esto.


Puedes usar una sesión para almacenar el hash

import hashlib def contact(request): if request.method == ''POST'': form = MyForm(request.POST) #join all the fields in one string hashstring=hashlib.sha1(fieldsstring) if request.session.get(''sesionform'')!=hashstring: if form.is_valid() : request.session[''sesionform''] = hashstring #do some stuff... return HttpResponseRedirect(''/thanks/'') # Redirect after POST else raise SubmissionWasDuplicate("duplicate") else: form = MyForm()

Con este enfoque (sin eliminar la cookie de sesión), el usuario no puede volver a almacenar los datos. La sesión caduca, por cierto, supongo que existe algo que identifica al usuario que envía los datos.


Siempre es bueno usar el método redirect-after-post. Esto evita que el usuario vuelva a enviar el formulario accidentalmente utilizando la función de actualización desde el navegador. También es útil incluso cuando usas el método hash. Esto se debe a que, sin redirigir después de un POST, en caso de presionar el botón Atrás / Actualizar, el usuario verá un mensaje de pregunta acerca de volver a enviar el formulario, lo que puede confundirla.

Si realiza una redirección GET después de cada POST, al presionar Atrás / Actualizar no se mostrará este mensaje extraño (para el usuario habitual). Por lo tanto, para una protección total, utilice Hash + redirect-after-post.


Una solución fácil para este problema es agregar un hash único a cada formulario. Entonces puedes tener una mesa rodante de formas actuales. Cuando se envía un formulario o el hash es demasiado antiguo, puede caducar fuera de su tabla y rechazar cualquier formulario que no tenga un hash coincidente en su tabla.

El HTTPRedirect es la forma correcta de hacerlo, como se mencionó anteriormente.

Desafortunadamente, incluso el propio administrador integrado de Django es propenso a problemas relacionados con este problema. En algunos casos, el marco de scripts entre sitios puede ayudar a prevenir algo de esto, pero me temo que las versiones de producción actuales simplemente no tienen esto incorporado.