Inicio > Django > Django + jqGrid

Django + jqGrid

En este post veremos como integrar jqGrid (potente grid basado en jQuery) en los templates Django.

Si desean una mayor usabilidad o quieren agregar un extra a sus aplicaciones web Django, este post les mostrará como hacerlo.

La administración en Django (admin Django) se basa en la utilización de una serie de vistas, por ejemplo tenemos la lista de cambios (template change_list.html) que tiene una serie de funcionalidades para buscar, ordenar, paginar y filtrar registros, también tenemos los formularios para agregar o modificar registros (template change_form.html).

Todas estas funcionalidades implican la recarga de toda la página o cargar nuevas páginas para su visualización(en el caso de los formularios para agregar o modificar un registro).

Como punto de partida mostrare una sencillo proyecto hecho en Django 1.2  para el registro de estudiantes (datos personales y carrera profesional en la que se encuentra); tenemos dos modelos en Django, Estudiante y Carrera, aquí se muestra el código y las vistas del admin Django que se generan.

Árbol de directorios:

  • proyecto/
    • app/
      • __init__.py
      • admin.py
      • models.py
      • views.py
      • test.py
    • media/ (copia del directorio ubicado en ‘/path_django/django/contrib/admin/media/’)
    • templates/ (copia del directorio ubicado en ‘/path_django/django/contrib/admin/templates/’)
    • __init__.py
    • manage.py
    • settings.py
    • urls.py

Aquí no explicare a detalle el deployment de la aplicación en Django 1.2, como un pequeño alcance lo estoy trabajando bajo apache y mod-wsgi, en el proyecto agrego dos directorios (media y templates); uno tiene el contenido estático(css, imágenes, javascript) y el otro  los templates .html base; estos directorios los he copiado del mismo core Django( ‘django/contrib/admin/templates’ y ‘django/contrib/admin/media’).

Solo bastará cambiar el parámetro TEMPLATE_DIRS del fichero settings.py apuntando al directorio templates y configurando el apache para que lea el contenido estático dentro del directorio media; todo eso ya es otro tema.

Archivo models.py

# -*- coding: utf-8 -*-
from django.db import models

GENDER_CHOICES = (
                     ('M', 'Masculino'),
                     ('F', 'Femenino'),
                 )

CIVIL_CHOICES = (
                    ('Soltero', 'Soltero'),
                    ('Casado', 'Casado'),
                    ('Viudo', 'Viudo'),
                    ('Divorciado', 'Divorciado'),
                )

class Carrera(models.Model):
    Codigo = models.CharField("Código",max_length=20,unique=True)
    Carrera = models.CharField( max_length=50)
    Observaciones = models.TextField(blank=True,null=True)

    def __unicode__(self):
        return self.Carrera

    class Meta:
        verbose_name = "Carrera Profesional"
        verbose_name_plural = "Carreras Profesionales"

class Estudiante(models.Model):
    Codigo = models.CharField("Código",max_length=7,unique=True)
    Nombres = models.CharField("Nombres",max_length=50)
    ApellidoPaterno = models.CharField("Ape. Pat.",max_length=50)
    ApellidoMaterno = models.CharField("Ape. Mat.",max_length=50)
    Nacimiento = models.DateField("Nacimiento",null=True,blank=True)
    Sexo = models.CharField(max_length=1,choices=GENDER_CHOICES)
    Direccion = models.CharField("Dirección",max_length=150,null=True,blank=True)
    Email = models.EmailField("E-mail",null=True,blank=True)
    EstadoCivil = models.CharField("Estado Civil",max_length=20,choices=CIVIL_CHOICES,default='Soltero')
    Telefono = models.CharField("Teléfono",max_length=20,null=True,blank=True)
    Carrera = models.ForeignKey(Carrera)
    Observaciones = models.TextField(blank=True,null=True)

    def __unicode__(self):
        return u'%s %s %s' % (self.ApellidoPaterno,self.ApellidoMaterno,self.Nombres)

    class Meta:
        verbose_name = "Estudiante"
        verbose_name_plural = "Estudiante"

Archivo admin.py


# -*- coding: utf-8 -*-
from django.contrib import admin
from proyecto.app.models import Estudiante, Carrera

class EstudianteAdmin(admin.ModelAdmin):
    list_display = ('Codigo','__unicode__','Nacimiento','Direccion','Email','Telefono','Carrera')
    search_fields = ('Nombres','ApellidoPaterno','ApellidoMaterno',)
    radio_fields = { "Sexo": admin.HORIZONTAL}
    list_filter = ('Carrera',)
admin.site.register(Estudiante, EstudianteAdmin)

class CarreraAdmin(admin.ModelAdmin):
    list_display = ('Carrera','Codigo')
    search_fields = ('Carrera','Codigo')
admin.site.register(Carrera, CarreraAdmin)

Habilitamos el admin en el archivo urls.py


from django.conf.urls.defaults import *

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
 # Example:
 # (r'^proyecto/', include('proyecto.foo.urls')),

 # Uncomment the admin/doc line below to enable admin documentation:
 # (r'^admin/doc/', include('django.contrib.admindocs.urls')),

 # Uncomment the next line to enable the admin:
  (r'^admin/', include(admin.site.urls)),
)

Con estos archivos generaremos las siguientes vistas estandar Django:

  • Listado de Estudiantes.


Listado de estudiantes.

  • Formulario para agregar estudiantes.

Add form

  • Formulario para modificar estudiantes.

Modificar estudiante.

Para empezar a trabajar con el jqGrid, debemos descargarlo de la pagina oficial, aquí esta la dirección de descarga  http://www.trirand.com/blog/?page_id=6

Trabajaremos con la version 3.8.1, la carpeta descargada (jqgrid3.8.1) la ubicaremos en nuestro directorio media por ser contenido estático, exactamente dentro de ‘proyecto/media/js/’

Si desean pueden chequear la documentación oficial (jqGrid Wiki Site), esta muy bien explicado.

A continuación vamos a crear nuestras propias vistas que reemplacen a las vistas estándar Django, todas ellas se encontraran en el archivo views.py, recuerden que deben actualizar el archivo urls.py agregando las urls que llamen a dichas vistas.

Sobreescribir listado de estudiantes (archivo views.py), con la vista jqgrid_estudiante.


# -*- coding: utf-8 -*-
#import necesarios para trabajar.
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect, HttpResponse
from django.template import RequestContext
from proyecto.app.models import Estudiante
from proyecto.app.models import Carrera
from django.utils import simplejson
from django.utils.safestring import mark_safe
#imports para la paginacion
from django.core.paginator import Paginator, InvalidPage, EmptyPage

def jqgrid_estudiante(request):
    if request.user.is_authenticated() and request.user.has_perm('app.add_estudiante') or request.user.has_perm('app.change_estudiante') or request.user.has_perm('app.delete_estudiante'):
        return render_to_response("jqgrid_estudiante.html", { "user": request.user }, context_instance = RequestContext(request))
    else:
        return HttpResponseRedirect('../../')

Esta vista renderiza el archivo jqgrid_estudiante.html, el cual posee el codigo que llama al grid con todos sus componentes, aqui mostramos su contenido.


{% extends "admin/base_site.html" %}
{% load adminmedia admin_list i18n %}

{% block extrastyle %}
 {{ block.super }}
 <link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/changelists.css" />
 {{ media }}

<!-- Llamamos a los archivos que se necesitan para construir el jqgrid -->
<link rel="stylesheet" type="text/css" media="screen" href="{% admin_media_prefix %}js/jqgrid3.8.1/css/redmond/jquery-ui-1.8.2.custom.css" />
<link rel="stylesheet" type="text/css" media="screen" href="{% admin_media_prefix %}js/jqgrid3.8.1/css/ui.jqgrid.css" />

<script src="{% admin_media_prefix %}js/jqgrid3.8.1/js/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="{% admin_media_prefix %}js/jqgrid3.8.1/js/i18n/grid.locale-es.js" type="text/javascript"></script>
<script src="{% admin_media_prefix %}js/jqgrid3.8.1/js/jquery.jqGrid.min.js" type="text/javascript"></script>
{% endblock %}

{% block bodyclass %}change-list{% endblock %}

 {% block breadcrumbs %}
<div>
 › Demostración jqGrid en Django</div>
 {% endblock %}

{% block coltype %}flex{% endblock %}

{% block content %}

<table id="jqgrid_estudiante"></table>
<div id="pagernav"></div>
<!-- pasamos los argumentos de los permisos que tiene el usuario -->
<input type="hidden" id="grid_perms_add" value="{{ perms.app.add_estudiante }}"/>
<input type="hidden" id="grid_perms_change" value="{{ perms.app.change_estudiante }}"/>
<input type="hidden" id="grid_perms_delete" value="{{ perms.app.delete_estudiante }}"/>

<script src="{% admin_media_prefix %}js/jqgrid_estudiante.js" type="text/javascript"> </script>
{% endblock %}

Archivo jqgrid_estudiante.js


//verificamos los permisos del usuario y asignamos variables(true, false)
if (jQuery("#grid_perms_add").val() == 'True'){
var add_grid = true ;
}else{
var add_grid = false;
}

if (jQuery("#grid_perms_change").val() == 'True'){
var edit_grid = true ;
}else{
var edit_grid = false;
}

if (jQuery("#grid_perms_delete").val() == 'True'){
var del_grid = true ;
}else{
var del_grid = false;
}

jQuery("#jqgrid_estudiante").jqGrid({
//url que llama a la base de datos y trae el listado de estudiantes, traemos los datos en formato json.
url:'ver/?add=' + jQuery("#grid_perms_add").val() + '&change=' + jQuery("#grid_perms_change").val() + '&delete=' + jQuery("#grid_perms_delete").val(),
datatype: "json",
colNames:['Nº','Código','Ape. Pat.','Ape. Mat.','Nombres','Nacimiento','Sexo','Dirección','Email','Teléfono','Estado Civil','Carrera','Observaciones'],
colModel:[

 {name:'id',index:'id',width:40,search:false,align:'center',editable:false,editoptions:{readonly:true,size:10}},

 {name:'Codigo',index:'Codigo',width:70,align:'center',editable:true,editoptions:{size:40},editrules:{required:true}},

 {name:'ApellidoPaterno',index:'ApellidoPaterno',width:80,align:'center',editable:true,editoptions:{size:40},editrules:{required:true}},

 {name:'ApellidoMaterno',index:'ApellidoMaterno',width:80,align:'center',editable:true,editoptions:{size:40},editrules:{required:true}},

 {name:'Nombres',index:'Nombres',width:80,align:'center',editable:true,editoptions:{size:40},editrules:{required:true}},

 {name:'Nacimiento',index:'Nacimiento',width:90,search:false,align:'center',editable:true,editoptions:{size:40},editrules:{required:false,date:true}},

 {name:'Sexo',index:'Sexo',width:55,search:false,editable:true,align:'center',edittype:"select",editoptions:{value:"M:Masculino;F:Femenino"},editrules:{required:true}},

 {name:'Direccion',index:'Direccion',search:false,width:150,align:'center',editable:true,editoptions:{size:40},editrules:{required:true}},

 {name:'Email',index:'Email',width:125,search:false,editable:true,editoptions:{size:40},editrules:{required:false,email:true}},

 {name:'Telefono',index:'Telefono',width:80,search:false,align:'center',editable:true,editoptions:{size:10},editrules:{required:false}},

 {name:'EstadoCivil',index:'EstadoCivil',width:70,search:false,align:'center',editable:true,edittype:"select",editoptions:{value: "Soltero:Soltero;Casado:Casado;Viudo:Viudo;Divorciado:Divorciado"},editrules:{required:true}},

 {name:'Carrera',index:'Carrera',width:130,search:false,editable:true,edittype:"select",editoptions:{dataUrl:'obtener_carreras/'},editrules:{required:true}},

 {name:'Observaciones',index:'Observaciones',width:110,search:false,editable:true,edittype:"textarea",editoptions:{rows:"3",cols:"37"},editrules:{required:false}}
],
rowNum:10,
rowList:[10,20,30],
pager: '#pagernav',
sortname: 'id',
viewrecords: true,
sortorder: 'desc',
caption:'Estudiantes',
//ruta para ejecutar las operaciones de agregar, modificar o eliminar un registro
editurl:'master/?add=' + jQuery("#grid_perms_add").val() + '&change=' + jQuery("#grid_perms_change").val() + '&delete=' + jQuery("#grid_perms_delete").val(),
height:'100%',
width: '100%'

});

jQuery("#jqgrid_estudiante").jqGrid('navGrid','#pagernav',
{search:true,add:add_grid,edit:edit_grid,del:del_grid}, //options
{width:400,height:430,reloadAfterSubmit:true,closeAfterEdit: true}, // edit options
{width:400,height:430,reloadAfterSubmit:true,closeAfterAdd: true}, // add options
{width:270,reloadAfterSubmit:true}, // del options
{} // search options
);

Vista que procesa el parámetro url (‘admin/app/estudiante/ver/’) del archivo jqgrid_estudiante.js mostrado lineas arriba.


def ver_jqgrid_estudiante(request):
    if request.user.is_authenticated():
        page = request.GET.get('page','')
        limit = request.GET.get('rows', '')
        sidx = request.GET.get('sidx', '')
        sord = request.GET.get('sord', '')
        busqueda = request.GET.get('_search','')

        if sord == 'asc':
            sord = '-'
        elif sord == 'desc':
            sord = ''

        students = Estudiante.objects.all()

        if busqueda == 'true':
            campo = request.GET.get('searchField','')
            operacion = request.GET.get('searchOper','')
            palabra = request.GET.get('searchString','')

            if campo == 'Codigo':
                if operacion == "eq":
                    students = students.filter(Codigo__exact = palabra)
                elif operacion == "nq":
                    students = students.exclude(Codigo__exact = palabra)
                elif operacion == "bw":
                    students = students.filter(Codigo__startswith = palabra)
                elif operacion == "bn":
                    students = students.exclude(Codigo__startswith = palabra)
                elif operacion == "ew":
                    students = students.filter(Codigo__endswith = palabra)
                elif operacion == "en":
                    students = students.exclude(Codigo__endswith = palabra)
                elif operacion == "cn":
                    students = students.filter(Codigo__contains = palabra)
                elif operacion == "nc":
                    students = students.exclude(Codigo__contains = palabra)
            elif campo == 'ApellidoPaterno':
                if operacion == "eq":
                    students = students.filter(ApellidoPaterno__exact = palabra)
                elif operacion == "nq":
                    students = students.exclude(ApellidoPaterno__exact = palabra)
                elif operacion == "bw":
                    students = students.filter(ApellidoPaterno__startswith = palabra)
                elif operacion == "bn":
                    students = students.exclude(ApellidoPaterno__startswith = palabra)
                elif operacion == "ew":
                    students = students.filter(ApellidoPaterno__endswith = palabra)
                elif operacion == "en":
                    students = students.exclude(ApellidoPaterno__endswith = palabra)
                elif operacion == "cn":
                    students = students.filter(ApellidoPaterno__contains = palabra)
                elif operacion == "nc":
                    students = students.exclude(ApellidoPaterno__contains = palabra)
            elif campo == 'ApellidoMaterno':
                if operacion == "eq":
                    students = students.filter(ApellidoMaterno__exact = palabra)
                elif operacion == "nq":
                    students = students.exclude(ApellidoMaterno__exact = palabra)
                elif operacion == "bw":
                    students = students.filter(ApellidoMaterno__startswith = palabra)
                elif operacion == "bn":
                    students = students.exclude(ApellidoMaterno__startswith = palabra)
                elif operacion == "ew":
                    students = students.filter(ApellidoMaterno__endswith = palabra)
                elif operacion == "en":
                    students = students.exclude(ApellidoMaterno__endswith = palabra)
                elif operacion == "cn":
                    students = students.filter(ApellidoMaterno__contains = palabra)
                elif operacion == "nc":
                    students = students.exclude(ApellidoMaterno__contains = palabra)
            elif campo == 'Nombres':
                if operacion == "eq":
                    students = students.filter(Nombres__exact = palabra)
                elif operacion == "nq":
                    students = students.exclude(Nombres__exact = palabra)
                elif operacion == "bw":
                    students = students.filter(Nombres__startswith = palabra)
                elif operacion == "bn":
                    students = students.exclude(Nombres__startswith = palabra)
                elif operacion == "ew":
                    students = students.filter(Nombres__endswith = palabra)
                elif operacion == "en":
                    students = students.exclude(Nombres__endswith = palabra)
                elif operacion == "cn":
                    students = students.filter(Nombres__contains = palabra)
                elif operacion == "nc":
                    students = students.exclude(Nombres__contains = palabra)

        estudiantes = students.order_by(str(sord) + str(sidx))

        n_estudiantes = estudiantes.count()
        paginator = Paginator(estudiantes, int(limit))

        try:
            page = request.GET.get('page', '1')
        except ValueError:
            page = 1

        try:
            resultados = paginator.page(page)
        except (EmptyPage, InvalidPage):
            resultados = paginator.page(paginator.num_pages)

        filas = []
        i = 1
        for r in resultados.object_list:
            fila = {"id" :r.id, "cell" :[i,r.Codigo,r.ApellidoPaterno,r.ApellidoMaterno,r.Nombres,str(r.Nacimiento),r.Sexo,r.Direccion,r.Email,r.Telefono,r.EstadoCivil,r.Carrera.Carrera,r.Observaciones]}
            filas.append(fila)
            i+=1
        results = {"page": page,"total": paginator.num_pages ,"records": n_estudiantes,"rows": filas }
        return HttpResponse(simplejson.dumps(results, indent=4),mimetype='application/json')
else:
    return HttpResponseRedirect('../../../')

Vista que procesa el parámetro editurl (‘admin/app/estudiante/master/’) del archivo jqgrid_estudiante.js mostrado lineas arriba.


def master_jqgrid_estudiante(request):
    if request.user.is_authenticated() and request.GET.get('add','') == 'True' or request.GET.get('change','') == 'True' or request.GET.get('delete','') == 'True':
        operacion = request.POST['oper']
        estudiante_id = request.POST['id']

        if operacion == "add" or operacion == "edit":
            codigo = request.POST['Codigo']
            ape_pat = request.POST['ApellidoPaterno']
            ape_mat = request.POST['ApellidoMaterno']
            nombres = request.POST['Nombres']
            nac = request.POST['Nacimiento']
            sexo = request.POST['Sexo']
            direccion = request.POST['Direccion']
            email = request.POST['Email']
            civil = request.POST['EstadoCivil']
            tel = request.POST['Telefono']
            carrera_id = request.POST['Carrera']
            obs = request.POST['Observaciones']

        if operacion == "add":
            guardar_estudiante = Estudiante(Codigo = codigo, ApellidoPaterno = ape_pat,ApellidoMaterno = ape_mat, Nombres = nombres, Nacimiento = nac,Sexo = sexo,Direccion = direccion,Email = email, EstadoCivil = civil,Telefono = tel, Carrera_id = carrera_id,Observaciones = obs)
            guardar_estudiante.save()
        elif operacion == "edit":
            obj_estudiante = Estudiante.objects.get(id = estudiante_id)
            obj_estudiante.Codigo = codigo
            obj_estudiante.ApellidoPaterno = ape_pat
            obj_estudiante.ApellidoMaterno = ape_mat
            obj_estudiante.Nombres = nombres
            obj_estudiante.Nacimiento = nac
            obj_estudiante.Sexo = sexo
            obj_estudiante.Direccion = direccion
            obj_estudiante.Email = email
            obj_estudiante.EstadoCivil = civil
            obj_estudiante.Telefono = tel
            obj_estudiante.Carrera_id = carrera_id
            obj_estudiante.Observaciones = obs
            obj_estudiante.save()
        elif operacion == "del":
            obj_estudiante = Estudiante.objects.get(id = estudiante_id)
            obj_estudiante.delete()
        return jqgrid_estudiante(request)
else:
    return HttpResponseRedirect('../../../')

En la configuración del formulario jqgrid mostramos un combobox donde se muestran las carrera profesionales,este campo tiene un parámetro denominado dataUrl que llama a la url ‘obtenercarreras/’, esta url es procesada por la vista obtener_carreras mostrada a continuación.Este combobox es llenado dinamicamente a medida que agreguemos nuevas carreras profesionales al modelo.

def obtener_carreras(request):
    if request.user.is_authenticated():
        carreras = Carrera.objects.all()
        inicio_select = "<select>"
        opciones = ""
        for c in carreras:
            opcion = "<option value='%s'>%s</option>" % (c.id, c.Carrera)
            opciones += opcion
        fin_select = "</select>"
        select = inicio_select + opciones + fin_select
        return HttpResponse(mark_safe(select))
    else:
        return HttpResponseRedirect('../../../')

Por último agregamos al archivo urls.py la siguientes lineas que corresponden a todas las vistas creadas:


from django.conf.urls.defaults import *

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
#importamos todas las vistas del archivo views.py
from proyecto.app.views import *
admin.autodiscover()

urlpatterns = patterns('',
 # Example:
 # (r'^proyecto/', include('proyecto.foo.urls')),

 # Uncomment the admin/doc line below to enable admin documentation:
 # (r'^admin/doc/', include('django.contrib.admindocs.urls')),

 # Uncomment the next line to enable the admin:
 (r'^admin/app/estudiante/$', jqgrid_estudiante),#cargar el template listado de estudiantes.
 (r'^admin/app/estudiante/ver/$', ver_jqgrid_estudiante),#cargar el jqgrid con la data del modelo estudiante, asi como busquedas y ordenar.
 (r'^admin/app/estudiante/obtener_carreras/$', obtener_carreras),#obtener las carreras de manera dinámica
 (r'^admin/app/estudiante/master/$', master_jqgrid_estudiante),#ejecutar operaciones de agregar, modificar o eliminar registros
 (r'^admin/', include(admin.site.urls)),
)

El código anterior se resume en las siguientes imágenes.

  • Listado de estudiantes.

jqgrid listado de estudiantes

  • Buscar estudiante.

jqgrid  buscar estudiantes

  • Agregar Estudiante.

jqgrid  agregar estudiantes

  • Modificar estudiante.

jqgrid  modificar estudiante

  • Eliminar estudiante.

jqgrid  eliminar estudiante
Como pueden observar el listado y el mantenimiento de los registros se realizan al instante sin cargar otras páginas,los formularios validan los datos ingresados, solo debes configurar que campos son requeridos y de que tipo son(emails, números, texto,etc), además jqGrid tiene una serie de opciones adicionales por ejemplo editar los registros inline, o manejar subgrids, treegrids,editar celdas, etc.Todo es cuestión de leer la documentación, luego verificar que urls debe procesar el django. La integración se hace fácil.
Espero les haya gustado y ojala les sirva y lo utilicen en sus aplicaciones, en mi caso yo lo he utilizado para crear una aplicación que permita editar en linea el registro de calificaciones de estudiantes, mejorando la usabilidad.
Hasta pronto.

Categorías: Django
  1. Joran
    febrero 3, 2011 a las 8:43 am

    Estimado MiguelVEL, traté de implementar el ejemplo utilizando jqgrid3.8.2 Sin embargo cada vez que intento acceder a la url /ver/ /obtener_carreras/ o /master obtener la devolución del objeto con u’ver clave principal Estudiante «o u’obtener_carreras ou ‘master no existe. ¿podría ayudarme? jqgrid mt quería implementar … y estoy aprendiendo con el ejemplo.

    • febrero 4, 2011 a las 7:40 pm

      Hola Joran, estas tres urls se configuran en el archivo jqgrid_estudiante.js
      en el archivo urls.py debes asociarlas a un respectivo método (def), por ejemplo la url (r’^admin/app/estudiante/ver/$’, ver_jqgrid_estudiante), mapea al metodo ver_jqgrid_estudiante y muestra la lista de estudiantes.

      Seguro no estas configurando bien tus urls por eso es que no procesa la url con la vista respectiva. como esa peticion se ejecuta internamente por el jquery asi no mas no la observas.
      Yo uso un plugin de firefox llamado firebug, el cual muestra todas las peticiones que se realizan, ahi observaras de una mejor manera las urls que se ejecutan y veras si devuelve un 200 ok, en caso no se ejecuta bien observaras un error 500.

      espero haya aclarado tus dudas.

  2. Joran
    febrero 7, 2011 a las 9:47 am

    Hola Michael, traté de hacer lo que dijo, sin embargo, sin éxito, sería posible para ofrecerle el proyecto presentado con la aplicación? porque he copiado todo el código fuente disponible aquí en el blog con el paso a paso .. es capaz de ejecutar correctamente Lo siento por los españoles y lo malo porque yo soy brasileño.

    • febrero 7, 2011 a las 10:12 pm

      Hola Joran, la verdad no se en que puedes estar fallando, me dices que has copiado el código fuente, pero he estado revisándolo y me he dado cuenta que al momento de copiar el codigo no se han copiado algunas cosas en el template jqgrid_estudiante.html(por ejemplo llamar al archivo jqgrid_estudiante.js), pero ya lo arregle. Si sigues teniendo dudas, y no corre la aplicación dame tu correo y yo te mando el proyecto en django para q te guíes, de no ser así, explícame con mas detalle tu problema, para poder ayudarte.

  3. Lapin-Blanc
    abril 23, 2011 a las 5:33 am

    Hi, thank you for this tutorial !
    as a suggestion, I post a small function wich reduce the number of line of codes for filtering the results:

    def filter_jqgrid_object_list(liste, champ, operation, argument):
    op_mapping = {
    «eq»:(«filter»,»__exact»),
    «nq»:(«exclude»,»__exact»),
    «bw»:(«filter»,»__startswith»),
    «bn»:(«exclude»,»__startswith»),
    «ew»:(«filter»,»__endswith»),
    «en»:(«exclude»,»__endswith»),
    «cn»:(«filter»,»__contains»),
    «nc»:(«exclude»,»__contains»),
    «lt»:(«filter»,»__lt»),
    «le»:(«filter»,»__lte»),
    «gt»:(«filter»,»__gt»),
    «ge»:(«filter»,»__gte»),
    }
    if operation in op_mapping:
    fonction = eval(‘liste.’+op_mapping[operation][0])
    arg_name = champ + op_mapping[operation][1]
    liste = fonction(**{arg_name : argument})
    return liste

    • abril 28, 2011 a las 12:08 am

      La idea de este ejemplo es solo para mostrar como se realiza la integración de Django y jqGrid, se puede mejorar el codigo en python como muestras, pero al final la lógica es la misma. Gracias por tu aporte.

  4. noviembre 6, 2011 a las 2:05 pm

    Muy buen tutorial…

  5. julio 8, 2013 a las 12:53 pm

    saludos aun siguen ahi XD ????? ,buena iniciativa! que bien! estado implementando el jqgrid ,aun tengo problemas poco a poco los esto resolviendo .. dado que no estoy usando los *media ,* templates de django estado haciendolo yo mismo ya que algunas librerias no la encuentro (css) pero creo que podria mostrarme algo..
    me sale el siguiente error

    /usr/local/lib/python2.7/dist-packages/django/template/loader.py in find_template, line 139
    estoy usando jqgrid4.5.2 .

  6. Ernesto Javier Rua Aguirre
    septiembre 14, 2013 a las 3:34 pm

    Me base en en tutorial para usarlo Django 1.5 y JqGrid pero tento el pequeño detall en la Edicion por csrf_token me genera 403, en que me puedes ayudar?

  7. Ernesto Javier Rua Aguirre
    septiembre 28, 2013 a las 1:26 pm

    Hola Miguel, gracias a tu ayuda pude solucionarlo el inconveniente, en estos momentos tengo un pequeño problema y es el siguiente cuando intento editar un GRID me funciona pero cuando intento adicionar o borrar me genera un error de «multivaluedictkeyerror» key not found, lo raro es que otros grid me funcionando con todas la operaciones CRUD, pero este caso no!, y este no tiene nada en particular, puedes ayudarme?

    • octubre 11, 2013 a las 9:02 am

      Para poder ayudarte necesito observar el error que te muestra en detalle, y que url o que acción lo provoca, el “multivaluedictkeyerror” se debe a varios motivos pero seria bueno que me indiques el detalle del error (si puedes envíame la pantalla amarilla del debug). Saludos.

  8. Ariel Benitez
    febrero 24, 2016 a las 2:57 pm

    Hola he tratado de implementar jqgrid pero sin lograrlo. Si bien no es de mi interes aplicar jqgrid al admin, si quicierea poder representar algun tipo de información en formato de grilla en la página.

    para ello estoy haciendo lo siguiente.

    $(«#list»).jqGrid({
    url: ‘/pres/ver/’,
    datatype: «json»,
    colNames:[«Apellido y Nombre», «Cuit»,»Iva», «mail», «telefono», «contacto», «especialidad»],
    colModel: [
    { name: «ayn», width: 55 },
    { name: «cuit», width: 90 },
    { name: «iva», width: 80, align: «right» },
    { name: «mail», width: 80, align: «right» },
    { name: «telefono», width: 80, align: «right» },
    { name: «contacto», width: 150, align: «right» },
    { name: «especialidad», width: 150, align: «right» }
    ],
    pager: «#pager»,
    rowNum: 10,
    rowList: [10, 20, 30],
    sortname: «ayn»,
    sortorder: «desc»,
    viewrecords: true,
    autoencode: true,
    caption: «Grilla Prestadores»,
    });

    $(«#list»).jqGrid(‘navGrid’,’#pager’,
    {search:false}, //options
    {width:400,height:430,reloadAfterSubmit:true,closeAfterEdit: true}, // edit options
    {width:400,height:430,reloadAfterSubmit:true,closeAfterAdd: true}, // add options
    {width:270,reloadAfterSubmit:true}, // del options
    {} // search options
    );

    views.py
    class ver_jqgrid_prestador(TemplateView):

    def get(self, request, *args, **kwargs):
    page = 1
    total = 1
    records = 1
    result = {‘total’: total,
    ‘pages’: page,
    ‘records’: records,
    ‘rows’: {‘id’: ‘1’, ‘cell’: [‘ariel’, ‘20246000965’, ‘RI’, ‘agsbenie@gmail.com’, ‘460070’, », »]}}
    return HttpResponse(
    json.dumps(result), content_type=’application/json’)

    urls.py

    url(r’^prestadoresgrid/’, views.jpgrid_prestadores,
    {‘plantilla’: ‘grilla.html’}),
    url(r’^pres/ver/’, views.ver_jqgrid_prestador.as_view()),

    en la página la grilla se dibuja, pero no muestra los datos que le estoy enviando. los cuales si llegan

    Alguna sugerencia que me puedan hacer???

  9. Ariel Benitez
    febrero 25, 2016 a las 10:59 am

    Hola Miguel. Sigues Ahí. Podría hacerte unas consultas??

    • febrero 25, 2016 a las 11:12 am

      Hola Ariel, estuve revisando tu código, la verdad no encuentro error alguno, tendría que ver el debug que aparece, si puedes me lo pasas, saludos.

  1. No trackbacks yet.

Deja un comentario