Cambiar valor de un field antes de valdidar formulario

2,889 views
Skip to first unread message

Jorge Luis Hernandez

unread,
Jul 31, 2011, 2:07:15 PM7/31/11
to djan...@googlegroups.com
Hola que tal,

Recien comienzo a usar Django y me esta encantando, de pronto no puedo
evitar compararlo con el framework que mejor manejo y que esta basado en
PHP como lo es Symfony, pero, a django le veo mucho potencial.

La duda es simple. Una vez que envio el formulario para validarlo, como
puedo alterar el valor de un field de este formulario antes de
validarlo ?

def add(request):
if request.method == "POST":
# Aqui quisiera modificar algún campo como la fecha para
que sea tomada del sistema.
form = myForm(request.POST)

if form.is_valid():
...

Saludos !

--
________________________________________________________

ISC. Jorge Luis Hernández C.
Desarrollador de Software y Tecnologías Libres

Usuario GNU/Linux Debian
http://lesthack.com.mx
@lesthack
________________________________________________________

signature.asc

Pedro Muñoz del Río

unread,
Jul 31, 2011, 5:04:19 PM7/31/11
to djan...@googlegroups.com
Hola

Eso podrías hacerlo en el mismo formulario, asignandole un valor por
defecto al campo mediante el parámetro initial al instanciarlo antes
de pasarselo al template.

https://docs.djangoproject.com/en/dev/ref/forms/fields/#initial

Saludos

2011/7/31 Jorge Luis Hernandez <lest...@gmail.com>:

--
Ing. Pedro Muñoz del Rio
CIP: 105362

------------------------------------------------
APESOL: http://www.apesol.org
Nuestros servicios: http://www.simuder.com

Jorge Luis Hernandez

unread,
Jul 31, 2011, 6:00:51 PM7/31/11
to djan...@googlegroups.com
Pero esto no me permite modificar a mi antojo, simplemente le doy un
valor por default.

Tratandose de un campo como fecha, si yo le añado un valor por default
al campo del formluario, tengo por lo tanto que incluirlo en el
template, aunque para que el usuario no lo vea lo he puesto como
HiddenInput, pero, esto da cabidad a que cualquer usuario al ver el
código del html, pueda alterar el valor del campo hidden de la fecha y
enviar otra que no es.

Como resolver ese problema ?

El dom, 31-07-2011 a las 16:04 -0500, Pedro Muñoz del Río escribió:
> Hola
>
> Eso podrías hacerlo en el mismo formulario, asignandole un valor por
> defecto al campo mediante el parámetro initial al instanciarlo antes
> de pasarselo al template.
>
> https://docs.djangoproject.com/en/dev/ref/forms/fields/#initial
>
> Saludos

signature.asc

Matías Bellone

unread,
Jul 31, 2011, 6:01:52 PM7/31/11
to djan...@googlegroups.com
2011/7/31 Jorge Luis Hernandez <lest...@gmail.com>:
> Pero esto no me permite modificar a mi antojo, simplemente le doy un
> valor por default.
>
> Tratandose de un campo como fecha, si yo le añado un valor por default
> al campo del formluario, tengo por lo tanto que incluirlo en el
> template, aunque para que el usuario no lo vea lo he puesto como
> HiddenInput, pero, esto da cabidad a que cualquer usuario al ver el
> código del html, pueda alterar el valor del campo hidden de la fecha y
> enviar otra que no es.
>
> Como resolver ese problema ?

Supongo que CSRF se encarga que no se modifiquen los campos que uno
envía... aunque no estoy seguro cómo funciona exactamente. Vas a tener
que averiguar un poco al respecto para confirmar, pero la solución
estoy seguro que es CSRF.

Saludos,
Toote
--
Web: http://www.enespanol.com.ar

Antoni Aloy

unread,
Jul 31, 2011, 6:11:17 PM7/31/11
to djan...@googlegroups.com
2011/8/1 Matías Bellone <matias...@gmail.com>:

> 2011/7/31 Jorge Luis Hernandez <lest...@gmail.com>:
>> Pero esto no me permite modificar a mi antojo, simplemente le doy un
>> valor por default.
>>
>> Tratandose de un campo como fecha, si yo le añado un valor por default
>> al campo del formluario, tengo por lo tanto que incluirlo en el
>> template, aunque para que el usuario no lo vea lo he puesto como
>> HiddenInput, pero, esto da cabidad a que cualquer usuario al ver el
>> código del html, pueda alterar el valor del campo hidden de la fecha y
>> enviar otra que no es.

La pregunta es, por qué poner la fecha en un formulario si la vas a
obtener del sistema? Si no quiero que el usuario altere una fecha no
la pongo en un formulario, si hay que presentarla se pasa como
parámetro adicional en el template.

Si quieres que una vez el usuario ha completado el formulario éste
devuelva un tipo de dato distinto, por ejemplo una instancia de un
modelo, puedes hacerlo en el método clean de cada campo.

Si tienes datos que tienes que mantener en diferentes páginas utiliza
las sesiones.

Saludos,

--
Antoni Aloy López
Blog: http://trespams.com
Site: http://apsl.net

Jorge Luis Hernandez

unread,
Jul 31, 2011, 6:19:18 PM7/31/11
to djan...@googlegroups.com
El dom, 31-07-2011 a las 19:01 -0300, Matías Bellone escribió:
> Supongo que CSRF se encarga que no se modifiquen los campos que uno
> envía... aunque no estoy seguro cómo funciona exactamente. Vas a tener
> que averiguar un poco al respecto para confirmar, pero la solución
> estoy seguro que es CSRF.
>
> Saludos,
> Toote

Implemento la protección contra ataques del tipo csrf, sin embargo, lo
que comento de poder alterar el valor de un campo cuando este es del
tipo hidden es posible y no es un ataque csrf, incluso, acabo de hacer
la prueba, pude dar de alta un registro con la fecha de ayer, y el valor
default que he puesto en Initial es la de hoy.

En symfony por ejemplo, es posible modificar los valores de un
formulario antes o despues de validarlo, supongo los formularios de
django pueden ser igual de flexibles pero aun no encuentro como hacerlo.

Saludos !

signature.asc

Jorge Luis Hernandez

unread,
Jul 31, 2011, 6:25:39 PM7/31/11
to djan...@googlegroups.com
El lun, 01-08-2011 a las 00:11 +0200, Antoni Aloy escribió:
> La pregunta es, por qué poner la fecha en un formulario si la vas a
> obtener del sistema? Si no quiero que el usuario altere una fecha no
> la pongo en un formulario, si hay que presentarla se pasa como
> parámetro adicional en el template.
>
> Si quieres que una vez el usuario ha completado el formulario éste
> devuelva un tipo de dato distinto, por ejemplo una instancia de un
> modelo, puedes hacerlo en el método clean de cada campo.
>
> Si tienes datos que tienes que mantener en diferentes páginas utiliza
> las sesiones.
>
> Saludos,

Si exacto, ese es el fin de mi pregunta inicial de este hilo, no quiero
incluir el campo de la fecha en mi formulario, aunque si es un campo de
mi modelo.

Estoy checando el método clean para este campo, si tengo dudas vuelvo al
hilo.

Gracias !

signature.asc

Ariel Camino

unread,
Jul 31, 2011, 9:14:56 PM7/31/11
to djan...@googlegroups.com
El 31/07/11 19:01, Matías Bellone escribió:
Hola, CSRF no se encarga de que no se modifiquen los campos que el usuario envía, siempre se van a poder modificar los campos que el usuario envía, es algo en lo que nunca se puede confiar.

CSRF es para evitar un tipo de vulnerabilidad en el que un atacante, genera un elemento malicioso, que al ser interpretado por el navegador de un usuario en el que el sitio web confía (por ejemplo un usuario autenticado), genera un request, por ejemplo:

<img src="http://ejemplo.com/transferir?cuenta=alicia&cantidad=1000">

con mostrarle esa imagen a usuarios autenticados, en una aplicación vulnerable todos los que la vean estarían transfiriendo 1000 pesos a Alicia.

Saludos!
-- 
Ariel Camino

Raimon Esteve

unread,
Aug 16, 2011, 5:08:02 PM8/16/11
to djan...@googlegroups.com
Hola,
sin testarlo, lo primero que probaria seria algo asi (con trabajo con
otros frameworks)

form = NombreForm(request.POST)
form.nombrecampo = "assigno el valor"
print form

revisa doc sobre form
https://docs.djangoproject.com/en/dev/topics/forms/

refreegrata

unread,
Aug 17, 2011, 9:10:02 AM8/17/11
to Django-es
Poco recomendable, pero supongo que podría funcionar:

request.POST._mutable = True
request.POST['nombre-del-campo']='la fecha'
request.POST._mutable = False

Mario César

unread,
Aug 17, 2011, 9:58:07 AM8/17/11
to djan...@googlegroups.com
El 17/08/11 09:10, refreegrata escribió:
Lo mejor es que el extiendas la validación de una clase Form[1].

Hay un caso típico, imagina que tienes un formulario que tiene un campo donde pones etiquetas.

    Titulo      [ Mi post sobre Django ]
    Etiquetas   [ django, python ]
    Contenido   [ El contenido de mi post ... ]
    __fecha__   [21/09/2010]

    [> Enviar ]

Est formulario es generado por la siguiente clase Form

    class PostForm(forms.Form):
        title = forms.CharField("Título")
        content = forms.CharField("Contenido")
        tags = forms.CharField("Etiquetas")
        date = forms.DateField(widget=forms.HiddenInput())

El caso es que necesitamos validar que el campo 'tags' sea una cadena separada por comas, que el usuario de como mínimo 2, y ademas cuando pidamos el valor seria muy conveniente que nos devuelva una lista en lugar de una cadena. Para eso solo extendemos la validación para el campo.

Tambien obtener la fecha del navegador y realizar una validación.

    import datetime

    class PostForm(forms.Form):
        title = forms.CharField("Título")
        content = forms.CharField("Contenido")
        tags = forms.CharField("Etiquetas")
        date = forms.DateField(widget=forms.HiddenInput())

        def clean_date(self):
            # Supongamos que el frontend hay una instrucción javascript que
            # llenga este campo. Solo tenemos que validar que sea correcto
            #  --> ej: 21/09/2010
            browser_date = self.cleaned_data['date']
            try:
                date_obj = datetime.datetime.strptime(browser_date, "%d/%m/%Y")
            except:
                raise forms.ValidationError('No podemos obtener la fecha de su navegador')
           
            if datetime.datetime.now() < date_obj:
                raise forms.ValidationError('Lo siento, no puede usar fechas en el futuro')
            return date_obj

        def clean_tags(self):
            # Aquí puedes validar y hacer muchas cosas extrañas y divertidas
            tags = self.cleaned_data['tags'].split(',')
           
            # Convertimos en minusculas todas las etiquetas
            tags = [tag.lower() for tag in tags]
           
            # Removemos etiquetas repetidas
            tags = list(set(tags))

            # Una regla para requerir un mínimo de etiquetas
            if len(tags) < 2:
                raise forms.ValidationError('Por favor uso por lo menos dos etiquetas')

            # una lista negra
            if 'politica' in tags:
                raise forms.ValidationError('Lo sentimos no hablamos de politica en este blog')
            elif 'phyton' in tags:
                raise forms.ValidationError('Tiene un error, la etiqueta correcta es "python"')
           
            # Finalmente retornamos la lista de etiquetas, toma atención
            # que estamos retornando una variable tipo lista, no es una cadena.           
            return tags

De esta forma cuando instancies tu formulario, puedes hacer esto :

        form = PostForm(request.POST)
        if form.is_valid():
            for tag in form.cleaned_data['tags']:
                as_algo_con_la_etiqueta(tag)

            # ojo form.cleaned_data['date'] es de tipo datetime.
            as_otra_cosa_con_la_fecha(form.cleaned_data['date'])

En general puedes hacer muchas cosas emocionantes con esto.




[1] Cleaning a specific field atribute
    https://docs.djangoproject.com/en/1.3/ref/forms/validation/#cleaning-a-specific-field-attribute


-- Mario César

raimonesteve

unread,
Aug 19, 2011, 5:26:54 AM8/19/11
to Django-es
On 31 jul, 20:07, Jorge Luis Hernandez <lesth...@gmail.com> wrote:
> La duda es simple. Una vez que envio el formulario para validarlo, como
> puedo alterar el valor de un field de este formulario antes de
> validarlo ?

Ahora que estoy con código, si quieres validar un campo, añadir un
valor por defecto (por ejemplo, la fecha de creación), etc, puedes
redifinir la classe save del modelo:

class Content(ContentBase):
....

def save(self):
self.updated_on = datetime.now()
super(Content, self).save()

En el ejemplo, cuando guardamos un formulario, el campo update_on se
añade la fecha actual.

En este ejemplo, hacemos uso de validación python. No JQuery.
Reply all
Reply to author
Forward
0 new messages