JCeb's Blog

Programación, investigación, proyectos, vida y mas…

Django con Jquery form y un image field latoso

con 3 comentarios

Ahora que andamos desarrollando la nueva versión de pikhub, andamos procurando un codigo hermoso, por lo que agregamos a nuestros javascripts uno llamado jquery.form, el plugin está bien chingon, te permite hacer peticiones por ajax sin necesidad de definir los parametros que solicita jquery y la petición por ajax la puedes armar a apartir de tu form.

Por ejemplo:

#!html
<form id="profile_form" class="ajax"
action="/settings/profile/" method="post"
enctype="multipart/form-data">
    {%csrf_token%}
    {{user_form.as_table}}
    {{profile_form.as_table}}
    <input type="submit" value="{%trans 'Enviar'%}" />
</form>

#!javascript
$('form.ajax').submit(function(){
        $(this).ajaxSubmit({
            dataType:  'json',
            success:  function(json){
                alert(json.message);
            }
        });
        return false;
    });

Y el codigo es generico pero hay un pequeño detalle, si dentro de los campos del formulario hay un imagefield y si tienes una versión del jquery.form del 2009 o 2010, la cosa no funcionará correctamente. Pero si en cambio tienes la versión 2011, todo funciona perfectamente, pero te diré que no es tan facil como parece, seguramente pensaras ah pues como es una petición por ajax, solo bastara con que en mi vista(views.py) haga esto:

@login_required
def profile(request):
    user = User.objects.get(username=request.user.username)
    profile = user.get_profile()
    profile_form = ProfileForm(instance=profile)
    alert = _(u'Datos guardados').encode('utf-8')
    user_form = UserForm(instance=user)
    if request.POST:
        user_form = UserForm(request.POST, instance=user)
        profile_form = ProfileForm(request.POST, request.FILES, instance=profile)
        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()
        else:
            alert = _(u'Datos incorrectos, intenta de nuevo').encode('utf-8')
    if request.is_ajax():
        json_obj = {'message' : alert, 'avatar':user.get_profile().avatar.url}
        return HttpResponse(json.dumps(json_obj))
    args = {
        'profile_form':profile_form,
        'user_form':user_form
    }
    return render('settings_profile.html', args, context_instance=rc(request))

El código permite que el formulario responda a HttpRequest y a XMLHttpRequest o ActiveXObject, gracias a la función is_ajax().

Pero permiteme desilusionarte, si esperas que al guardar tu formulario con una imagen en él, te va a responder satisfactoriamente, te sentaras a esperar porque jamas te responderá jeje. Esto debido a que jquery.form manda la imagen por medio de un iframe invisible para nosotros, un trucaso, pero hay que saber como tratarlo, por lo tanto, si deseamos que todo funcione bien, habrá que agregar un campo como comodin a nuestro formulario, en mi caso lo agregue con javascript, usando j2h.js(https://bitbucket.org/julianceballos/j2h/src/9c468b91cec7/j2h.min.js), de la siguiente forma:

$('#profile_form').append($.j2h('input',{
        'type':'hidden',
        'name':'xhr',
}));
$('#profile_form').submit(function(){
        $(this).ajaxSubmit({
            dataType:  'json',
            success:  function(json){
                alert(json.message);
            }
        });
        return false;
});

Así si el javascript está activado el formulario se irá con un campo de más oculto que se llama xhr.
Luego en la vista(views.py) solo habrá que revisar que ese campo existe y si existe quiere decir que estamos enviando por ajax los datos y jquery.form está haciendo sus trucos para subir la imagen sin recargar la página. Por lo que la vista queda:

@login_required
def profile(request):
    user = User.objects.get(username=request.user.username)
    profile = user.get_profile()
    profile_form = ProfileForm(instance=profile)
    alert = _(u'Datos guardados').encode('utf-8')
    user_form = UserForm(instance=user)
    if request.POST:
        user_form = UserForm(request.POST, instance=user)
        profile_form = ProfileForm(request.POST, request.FILES, instance=profile)
        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()
        else:
            alert = _(u'Datos incorrectos, intenta de nuevo').encode('utf-8')
    if request.POST.__contains__('xhr'):
        json_obj = {'message' : alert, 'avatar':user.get_profile().avatar.url}
        return HttpResponse(json.dumps(json_obj))
    args = {
        'profile_form':profile_form,
        'user_form':user_form
    }
    return render('settings_profile.html', args, context_instance=rc(request))

Y listo ahora todo debe funcionar perfectamente.

Advertisement

Escrito por JCeb

19 mayo, 2011 a 6:04 pm

Escrito en Uncategorized

3 comentarios

Suscríbete a los comentarios mediante RSS.

  1. if request.POST.__contains__(‘xhr’):

    cambia por:

    if request.POST.get(“xhr”, False):

    mas bonito y en tu formulario >> action=”/settings/profile/” usa {% url %} para no hacer DRY

    j2h.js ? reinventaste

    $(““, {href:’http://www.google.com’, text:”google”}).appendTo($(“body”));

    zoman

    24 mayo, 2011 a 6:39 pm

  2. jQuery( html, [ ownerDocument ] )

    zoman

    24 mayo, 2011 a 6:42 pm


Deja un comentario

Fill in your details below or click an icon to log in:

Logo de WordPress.com

You are commenting using your WordPress.com account. Log Out / Cambiar )

Twitter picture

You are commenting using your Twitter account. Log Out / Cambiar )

Facebook photo

You are commenting using your Facebook account. Log Out / Cambiar )

Connecting to %s

Seguir

Get every new post delivered to your Inbox.