ff-multiconverter, multimedia, audio, video, linux, ubuntu ubuntu kylin, china, releases, linux terminal, ubuntu, linux, comandos, shell conky, gadgets, ubuntu, linux SpeedTest-Cli, velocidad, red, consola, terminal tag foto 6 pinta, grafica, linux, ubuntu djl, juegos, yum, synaptic, paquetes ubuntu, releases, canonical psensor, ubuntu, linux, sistema, monitor

Guía de GHex editor hexadecimal de GNOME: preferencias.

Editar.
  • Número máximo de niveles de deshacer
  • Use esta casilla de selección para especificar el número máximo de acciones que puede deshacer.
  • Mostrar el desplazamiento del cursor en la barra de estado como
  • Use esta lista desplegable para seleccionar el formato en el que se mostrará el desplazamiento del cursor. El formato puede ser decimal, hexadecimal o una cadena de estilo de impresión personalizado que sólo contenga los especificadores de formato x, o y s.
  • Mostrar columna de los desplazamientos
  • Seleccione esta opción para visualizar los desplazamientos del cursor en una columna situada a la izquierda de la vista hexadecimal de la ventana Editor Hexadecimal de GNOME.
ghex2
Visualizar.
Tipografía
Use las cajas de selección de tipografía para editar la información existente sobre la tipografía o para escribir información nueva sobre ésta. Especifique un tipo, estilo y tamaño de tipografía para mostrar el contenido de los archivos en GHex.
Tipo de grupo predeterminado
Seleccione una de las siguientes opciones para especificar cómo GHex muestra el contenido hexadecimal de un archivo en la ventana de GHex:
  • Bytes: bytes únicos.
  • Palabras: grupos de dos bytes.
  • Palabras largas: grupos de cuatro bytes. Tipografía de los datos
Imprimir.
 
Pulse en el botón Fuente de los datos para especificar el tipo,estilo y tamaño de la tipografía que desea utilizar para imprimir los datos de un archivo.
 
Tipografía de las cabeceras
Pulse en el botón Tipografía de las cabeceras para especificar el tipo ,el estilo y el tamaño de la tipografía que desea utilizar para imprimir la información de cabecera de un archivo.
Sobreimprimir un recuadro sombreado
Use este cuadro de incremento para especificar el número de líneas que desea que el Editor hexadecimal de GNOME imprima dentro de un recuadro sombreado . Si el valor del cuadro de incremento es 10, el Editor hexadecimal de GNOME imprimirá las 10 primeras líneas del archivo sin el recuadro sombreado, y las 10 siguientes con el recuadro, y así sucesivamente. Si el valor del cuadro de incremento es 0, GHex no imprimirá ningun recuadro sombreado.
ghex-15
Si te ha gustado el artículo inscribete al feed clicando en la imagen más abajo para tenerte siempre actualizado sobre los nuevos contenidos del blog:

Guía de GHex editor hexadecimal de GNOME: editar un archivo

Para editar un archivo, ejecute los siguientes pasos:
  1. Pulse en la vista hexadecimal o ASCII del archivo. La vista en la que el cursor está activo muestra un cursor completo. La vista en la que el cursor no está activo muestra el contorno del cursor.
  2. Use cualquiera de los siguientes métodos para mover el cursor por el archivo:
    • Use la barra de desplazamiento de la ventana o las flechas del teclado para desplazarse a lo largo del archivo.
    • Seleccione Editar ▸ Ir a byte, introduzca el desplazamiento del cursor como un valor decimal o hexadecimal y, luego, haga clic en Aceptar. El formato del valor hexadecimal debe ser 0x seguido del desplazamiento, por ejemplo, 0x3.
  3. Edite el formato ASCII del mismo modo que edita un archivo de texto normal. Para editar el formato hexadecimal, use los valores del 0 a 9 y de la a a la f.
Para insertar datos sin sobrescribir los existentes, seleccione Editar ▸ Modo Insertar.
ghex-15
Para cortar, copiar, y pegar datos elija Editar ▸ Cortar, Editar ▸ Copiar, y Editar ▸ Pegar.
Para deshacer y editar elija Editar ▸ Deshacer. Para rehacer una acción elija Editar ▸ Rehacer. El número de ediciones previas que puede deshacer está determinado en la configuración de Número máximo de niveles de deshacer en la sección en pestañas Sección 4.1: Editar del cuadro de diálogoPreferences .
Guardar un archivo.
Para guardar un archivo, tiene dos opciones:
  • Para guardar cambios en el archivo actual, seleccione Archivo ▸ Guardar.
  • Para guardar el archivo actual bajo un nuevo nombre, seleccione Archivo ▸ Guardar como. Introduzca un nombre para el archivo en el cuadro de diálogo Seleccione el archivo donde quiere guardar el buffer actual y luego haga clic en Aceptar.
Revertir la última versión guardada de un archivo.
Para revertir a la última versión del archivo actual que haya guardado, y deshacer todas las ediciones que realizó en el archivo desde que lo guardó, elija Archivo ▸ Revertir, después pulse Sí en el cuadro de diálogo Pregunta.
Buscar datos en un archivo.
Para buscar una cadena hexadecimal o ASCII en un archivo, ejecute los siguientes pasos:
  1. Seleccione Editar ▸ Buscar.
  2. En el cuadro de diálogo Buscar los datos, seleccione una de las siguientes opciones:
    • Buscar datos hexadecimales
    • Buscar datos ASCII
  3. Escriba la cadena que desea encontrar.
  4. Pulse en Buscar siguiente para buscar la siguiente aparición de la cadena.
  5. Pulse en Buscar anterior para buscar la aparición anterior de la cadena.
  6. Pulse en Cancelar para cerrar el diálogo Buscar datos.
Realizar una búsqueda avanzada.
Para realizar una busqueda avanzada, ejecute los siguientes pasos:
  1. Seleccione Editar ▸ Búsqueda avanzada.
  2. En el cuadro de diálogo Buscar datos, seleccione el criterio de búsqueda requerido. Para obtener información acerca de cómo añadir nuevos criterios de búsqueda, consulte Sección 3.6: Añadir criterios de búsqueda.
  3. Pulse en Buscar siguiente para buscar la siguiente aparición de la cadena.
  4. Pulse en Buscar anterior para buscar la aparición anterior de la cadena.
  5. Pulse en Cerrar para cerrar el diálogo Buscar datos.
Añadir criterios de búsqueda.
Para añadir criterios de búsqueda, realice los siguientes pasos:
  1. Seleccione Editar ▸ Búsqueda avanzada.
  2. Pulse en Añadir nuevo dentro del cuadro de diálogo Buscar datos.
  3. En el cuadro de diálogo Añadir búsqueda, seleccione una de las siguientes opciones:
    • Buscar datos hexadecimales
    • Buscar datos ASCII
  4. Escriba la cadena que desea encontrar.
  5. Use la rueda de color o las casillas de selección para escoger un color para resaltar loscriterios de búsqueda.
  6. Pulse en Añadir.
  7. Pulse en Cancelar para cerrar el diálogo Buscar datos.
Eliminar criterios de búsqueda.
Para eliminar un criterio de búsqueda, siga los siguientes pasos:
  1. Seleccione Editar ▸ Búsqueda avanzada.
  2. En el cuadro de diálogo Buscar los datos, seleccione el criterio de búsqueda que desea eliminar.
  3. Pulse en Eliminar seleccionados.
  4. Pulse en Cancelar para cerrar el diálogo Buscar datos.
Buscar y reemplazar datos de un archivo.
Para buscar una cadena hexadecimal o ASCII en un archivo y luego reemplazarla, ejecute los siguientes pasos:
  1. Seleccione Editar ▸ Reemplazar.
  2. En la ventana de diálogo Buscar & reemplazar datos, seleccione una de las siguientes opciones:
    • Reemplazar datos hexadecimales
    • Reemplazar datos ASCII
  3. En el primer cuadro de texto, escriba la cadena que desea encontrar.
  4. En el segundo cuadro de texto, escriba la cadena con la que desea reemplazar la cadena que está buscando.
  5. Pulse en Buscar el siguiente.
  6. Pulse en Reemplazar para reemplazar la aparición actual de la cadena, o bien en Reemplazar todo para reemplazar todas las apariciones de la cadena.
  7. Pulse en Cancelar para cerrar el diálogo Buscar y reemplazar datos
Añadir o quitar vistas adicionales de un archivo.
Para añdir otra vista del archivo actual a la ventana de Editor Hexadecimal de GNOME, seleccione Ver ▸ Añadir vista.
Para quitar una vista del archivo actual, seleccione Ver ▸ Eliminar vista. Al cerrar el ultimo archivo abierto, también se cerrará la aplicación.
Cambiar el tipo de grupo de datos.
Para modificar la forma en que GHex muestra el contenidohexadecimal de un archivo en la ventana de GHex, seleccioneVer ▸ Agrupar datos como, y seleccione una de las siguientes opciones:
  • Bytes: bytes únicos.
  • Palabras: grupos de dos bytes.
  • Palabras largas: grupos de cuatro bytes.
Exportar la visualización de Editor Hexadecimal de GNOME a HTML.
Para exportar los datos de la ventana de GHex a HTML, seleccione Archivo ▸ Guardar como HTML. Seleccione una carpeta y especifique un nombre para el archivo HTML y pulse Aceptar. GHex implementa las siguientes acciones:
  • Crea un archivo HTML independiente para cada página de datos que se muestra en la ventana Editor Hexadecimal de GNOME.
  • Usa el nombre de archivo HTML que usted especifique como base para el nombre del archivo.
  • Adjudica un número de página al nombre del archivo para diferenciar los documentos.
Por ejemplo, si especifica el nombre del archivo log.html, GHex crea una serie de archivos HTML denominados log00000000.html, log00000001.html, log00000002.html, y así sucesivamente.
Ver una tabla de caracteres.
Para ver una tabla que contenga las representaciones ASCII, hexadecimales, decimales, octales y binarias de los valores que van de 0 a 255, seleccione Herramientas ▸ Tabla de caracteres.
Ver conversiones de datos.
Para visualizar conversiones binarias, decimales, hexadecimales y ASCII hasta un máximo de cuatro bytes de datos, ejecute los siguientes pasos:
  • Seleccione Herramientas ▸ Convertidor base.
  • Seleccione una de las siguientes opciones:
    • Escriba los datos que desea convertir en uno de los campos del cuadro de diálogo Convertidor base y pulse Intro.
    • Si desea ver las conversiones de los datos de la posición del cursor en el archivo abierto, haga clic en el botón Recuperar valor del cursor.
    Editor Hexadecimal de GNOME actualiza los valores de los demás campos para mostrar las conversiones de los datos.
  • Pulse en Cerrar para cerrar el diálogo Conversor de base.
Para mostrar u ocultar el cuadro de diálogo de conversión de tipo.
Para mostrar u ocultar el cuadro de diálogo de conversión de tipo, seleccioneVentanas ▸ Diálogo de conversión de tipo.
El cuadro de diálogo de conversión de tipos mustra el valor del carácter seleccionado en las siguientes representaciones:
  • 8 bits con signo
  • 8 bits sin signo
  • 16 bits con signo
  • 16 bits sin signo
  • 32 bits con signo
  • 32 bits sin signo
  • 32 bits en coma flotante
  • 64 bits en coma flotante
  • Hexadecimal
  • Octal
  • Binario
  • Longitud del flujo
El cuadro de diálogo de conversión de tipo también contiene las siguientes opciones:
  • Mostrar la decodificación en little endian
  • Seleccione esta opcion para mostrar la decodificación en little endian.
  • Mostrar como hexadecimal los números sin signo y en coma flotante
  • Seleccione esta opción para mostrar los números sin signo y en coma flotante como números hexadecimales.
Imprimir un archivo.
Para imprimir un archivo, seleccione Archivo ▸ Imprimir. Seleccione las opciones de impresión que necesita en el cuadro de diálogo Imprimir y, a continuación, pulse en Aceptar.
Para obtener una vista previa de una copia impresa del archivo, seleccione Archivo ▸ Vista previa de impresión.
ghex1
Si te ha gustado el artículo inscribete al feed clicando en la imagen más abajo para tenerte siempre actualizado sobre los nuevos contenidos del blog:

Los 10 artículos más leídos en El Mundo de Ubuntu en el mes de Agosto 2013.

1.- Ubuntu 13.04 disponible para descarga (Información de pantalla, video, tutorial).

raring ringtail open developmentCanonical oficialmente ha publicado su version 13.04 nombre en codigo “Raring Ringtail”
Se están notando las ventajas de optimizar el sistema operativo para dispositivos móviles con pocos recursos.
El sistema consume menos Ram y se agiliza su utilización.
Los cambios más destacados, respecto al consumo son:
  • Se ha reducido el uso de memoria que hacían algunos paquetes, cargando datos e imágenes CSS de GTK3, sólo cuando se necesitan.
  • Se arreglaron problemas de memoria en los paquetes libdbusmenu, update-notifier, upower, whoopsie y otros más.
  • LightDM PPS cayó de un uso de 25.7M a 0.6M
  • Algunos procesos fueron modificados para que terminen si no se usan y se reinicien cuando se demandan, por

2.- Como ajustar el volumen de tus archivos de audio con QtGain.

Qt-logo.svgQtGain es un frontend para MP3Gain, VorbisGain, AACGain y Metaflac.
Con el podrás ajustar automáticamente el volumen de tus archivos de audio. (MP3, MP4, Ogg-Vorbis y Flac)
Es sencillísimo de usar. Solo tienes que arrastrar los archivos de audio o carpetas a la ventana de QtGain para que inmediatamente se ponga a trabajar.
Si el archivo ya ha sido normalizado, solamente lo saltea y al finalizar te informa de la cantidad de archivos procesados, los que han sido normalizados, los que ha salteado y los que dieron error.
Ha sido actualizado a la versión 0.9.4 con esta lista de cambios:

3.- DJL es un instalador de juegos que proporciona una interfaz sencilla y muchas utilidades.

djl_depotDJL es es un administrador de juegos escrito en Python, que nos permitirá instalar una gran cantidad de títulos (ver el detalle al final del post) en Linux.
Es un gestor de juegos, que nos sirve tanto para lanzar los juegos que hemos instalado con él, como para instalar juegos desde la red
He mirado los juegos disponibles en el repositorio y no me puedo quejar, están tanto los más famosos como los no tan conocidos.
Para usarlo debemos descargar la última versión, descomprimirla e instalarla.

4.- Diseño Gráfico en Linux: completo videotutorial de Gimp (28 vídeos).
GIMP (GNU Image Manipulation Program) es un programa de edición de imágenes digitales en forma de mapa de bits, tanto dibujos como fotografías. Es un programa libre y gratuito. Forma parte del proyecto GNU y está disponible bajo la Licencia pública general de GNU.
Es el programa de manipulación de gráficos disponible en más sistemas operativos (Unix, GNU/Linux, FreeBSD, Solaris, Microsoft Windows y Mac OS X, entre otros).

5.- Guía HTML: introducción y estructura interna de una página.
En una reciente limpieza a mi disco duro he encontrado esta guia que tenia guardada por ahi y creo que esta muy buena para empezar y conocer las nociones basicas del HTML.
Introducción.
HTML es el lenguaje que se emplea para el desarrollo de páginas de internet.
Este lenguaje está constituido de elementos que el navegador interpreta y las despliega en la pantalla de acuerdo a su objetivo. Veremos que hay elementos para disponer imágenes sobre una página, hipervínculos que nos permiten dirigirnos a otra página, listas, tablas para tabular datos, etc.

6.- Gscan2pdf útil herramienta para extraer el texto de archivos pdf que han sido escaneados como imagen.
gscan2Les presento una herramienta muy útil para Debian, se trata de gscan2pdf. Este sencillo programa permite extraer el texto de archivos pdf que han sido escaneados como imagen, de manera similar que algunos ORC's de Windows. Su instalación es muy sencilla, viene en los repositorios de los discos y se puede instalar desde Synaptic, o se puede descargar de la página principal gscan2pdf.sourceforge.net/ . Además se va a necesitar el respectivo paquete de idioma que en mi caso es tesseract-orc-spa.

7.-  Instalar Angry Birds en Ubuntu 12.04 “Precise Pangolin”.

Angry_Birds_PlushiesAngry Birds  es un videojuego creado en 2009 por la empresa finlandesa Rovio Mobile. Desde entonces, el juego ha sido adaptado a dispositivos de pantalla táctil, como los basados en Maemo, iOS, Symbian, Java y Android.
Con más de un billón de descargas en 2012, esta aplicación quizá sea la más popular del año en la App Store de Apple. Además es también el juego más vendido de la historia en soportes móviles.

8.- Crack es el adivinador' de contraseñas más utilizado en entornos Unix
Crack, desarrollado por el experto en seguridad Alec Muffet, es el `adivinador' de contraseñas más utilizado en entornos Unix; actualmente se encuentra en su versión 522.5, que funciona correctamente en la mayoría de clones del sistema operativo (Linux, Solaris, OSF...).
Ejecutar periódicamente Crack sobre el fichero de contraseñas de sus sistemas es algo muy recomendable para cualquier administrador mínimamente preocupado por la seguridad, sin importar que se utilicen mecanismos para obligar a los usuarios a elegir passwords aceptables.

9.- Colección de iconos para Tux, el simpático pinguino de Linux.
Tuxguitar
10.- 4Pane navegador de archivos para Linux con cuatro paneles

4Pane-1 4Pane es un explorador de carpetas con el que no perdernos entre la enorme cantidad de ficheros del directorio raíz.
Su interfaz se divide en cuatro partes, para facilitar la navegación y poder mover ficheros de una carpeta a otra rápidamente, recordando al mítico Midnight Commander pero en versión gráfica.
A sus funciones como gestor de archivos incorpora otras, como enlaces a Firefox, Openoffice y el editor de texto, montaje de discos, particiones e ISOs, extracción de archivos comprimidos e incluso una lista de las carpetas que más solemos abrir y acceso al terminal.

Si te ha gustado el artículo inscribete al feed clicando en la imagen más abajo para tenerte siempre actualizado sobre los nuevos contenidos del blog:

Guía de GHex editor hexadecimal de GNOME: procedimientos iniciales.

La aplicación Editor hexadecimal de GNOME le permite ejecutar las siguientes acciones:
  • Visualizar un archivo en formato ASCII y hexadecimal de forma simultánea.
  • Editar un archivo en formato ASCII o hexadecimal.
Inicio de Editor Hexadecimal de GNOME.
Para iniciar Editor Hexadecimal de GNOME, siga los siguientes pasos:
Menú Aplicaciones
Seleccione Accesorios ▸ Editor hexadecimal.
Línea de comandos
Ejecute el siguiente comando: ghex
Al iniciar Editor Hexadecimal de GNOME
Al iniciar Editor Hexadecimal de GNOME, se muestra la siguiente ventana.
Ventana de Editor Hexadecimal de GNOME antes de abrir un archivo
Abrir un archivo.
Para abrir un archivo, seleccione Archivo ▸ Abrir. Seleccione el archivo que desea abrir y luego haga clic en Aceptar. Puede abrir múltiples archivos en Editor hexadecimal de GNOME. Editor Hexadecimal de GNOME muestra cada archivo en una nueva ventana.
Al abrir un archivo en Editor hexadecimal de GNOME, la aplicación muestra dicho archivo en la siguiente ventana.


Ventana de Editor Hexadecimal de GNOME con un archivo abierto
La ventana de Editor Hexadecimal de GNOME contiene los elementos siguientes:
Barra de menús
Los menús que aparecen en la barra de menú contienen todos los comandos necesarios para trabajar con archivos en Editor Hexadecimal de GNOME.
Una columna de desplazamientos del cursor
El desplazamiento del cursor es la distancia entre el comienzo del archivo y el primer byte de cada línea. De manera predeterminada, Editor Hexadecimal de GNOME muestra la columna de desplazamientos del cursor en la parte izquierda de la vista hexadecimal.
Panel de visualización en la parte izquierda
El panel de visualización ubicado en la parte izquierda del área de visualización muestra una vista hexadecimal del archivo.
Panel de visualización en la parte derecha
El panel de visualización ubicado en la parte derecha del área de visualización muestra una vista ASCII del archivo.
Diálogo de conversión de tipo
El cuadro de diálogo de conversión de tipo debajo del área de visualización muestra el valor del carácter seleccionado en distintos formatos numéricos.
Si te ha gustado el artículo inscribete al feed clicando en la imagen más abajo para tenerte siempre actualizado sobre los nuevos contenidos del blog:

10 configuraciones para Conky atractivas y minimalistas.

Conky es un software gratuito de monitor de sistema para el sistema X Window.

Conky es una aplicación de escritorio ideada con la finalidad de ofrecer información acerca del estado del sistema.
Por ejemplo:
  • El uso de la memoria.
  • Un historial del uso de la CPU.
  • Temperaturas.
  • Velocidades de ventiralores.
  • Hora-Fecha.
  • Estado del Disco Duro.
Está disponible para Linux, FreeBSD y OpenBSD.
Recuerden leer las instrucciones especificas de cada script, algunos necesitan ciertos plugins para poder mostrar el clima correctamente, y siempre es importante instalar las tipografías que usan, entre otros detalles.

Si te interesa profundizar el tema:

eOS
conky
Conky-Vision
Minimal
Black 2.0 Conky
simple
Conky Flipclock
10 configuraciones para Conky bonitas y minimalistas
Flat-Weather for Conky
bonito
Dark Pixel Conky
conky
Elementary Conky
Minimal
Cloud Conky
simple
Dinnamo Clock Conky
10 configuraciones para Conky bonitas y minimalistas
Helix Conky
bonito
Si te ha gustado el artículo inscribete al feed clicando en la imagen más abajo para tenerte siempre actualizado sobre los nuevos contenidos del blog:

Gscan2pdf útil herramienta para extraer el texto de archivos pdf que han sido escaneados como imagen.

Les presento una herramienta muy útil para Debian, se trata de gscan2pdf.
Este sencillo programa permite extraer el texto de archivos pdf que han sido escaneados como imagen, de manera similar que algunos ORC's de Windows.
Su instalación es muy sencilla, viene en los repositorios de los discos y se puede instalar desde Synaptic, o se puede descargar de la página principal gscan2pdf.sourceforge.net/ . Además se va a necesitar el respectivo paquete de idioma que en mi caso es tesseract-orc-spa.
gscan2
Como viene con interfaz gráfica es bastante intuitivo, pero de todas formas ahí va una pequeña intro de como sacarle el texto a un pdf formado de imagenes o una imagen.
1.- Abrimos la ventana principal.
2.- Despues vamos al menú Archivo y elegimos Importar, seleccionamos el archivo y abrir.
3.- Aparecerá una pequeña ventana indicandonos que páginas queremos analizar. 

Esto es puede traer un poco de problemas porque algunos documentos e imagenes están formados por capas y cambia el orden de las páginas.
4.- Ahora se nos mostrará las imagenes de las páginas que elejimos antes. 

5.- Por último, a lo que vine, buscamos la imagen que tenga texto, vamos al menú Herramientas, OCR y
se abre una ventana en la que elegimos el motor de busqueda y el idioma, seleccionamos Tessract. 

6.- Automaticamente el texto en forma de imagen es extraido y está listo para copiarse. 

En caso de querer sacarle texto a una imagen, en el paso 5, como motor elegimos GORC y se obtiene el texto aunque sin caracteres especiales ni tildes.
Espero que les sea útil y mas que todo les ahorre tiempo.
Capturas de pantallas.
gscan
gscan2pdf
gscan2pdf0.9.19_tesseract_fr
gscan3

Guia Python: alta, listado, consulta y borrado de datos (2a parte).

Python es un lenguaje de script desarrollado por Guido van Rossum.

Podemos codificar empleando programación lineal, estructurada y orientada a objetos (tengamos en cuenta que esta última es la que se ha impuesto en la actualidad).

Se cuenta con intérpretes de Python en múltiples plataformas: Windows, Linux, Mac etc. Se pueden desarrollar aplicaciones de escritorio como aplicaciones web. Empresas como Google, Yahoo, Nasa etc. utilizan este lenguaje para sus desarrollos (actualmente el creador de Python Guido van Rossum trabaja para Google.)

Se puede ejecutar instrucciones de Python desde la línea de comando o creando archivos con extensión *.py. Cuando uno comienza a aprender este lenguaje la línea de comandos nos provee una retroalimentación del resultado en forma inmediata.

El objetivo de este tutorial es presentar en forma progresiva los conceptos fundamentales de este lenguaje y poder analizar los problemas resueltos y codificar los problemas propuestos en este mismo sitio, sin tener que instalar en un principio el Python en su equipo (o luego de instalado poder avanzar con el tutorial en cualquier máquina conectada a internet).
python listasModificación de datos (App Engine).
Trabajaremos nuevamente con el problema de usuarios. Dispondremos un formulario que solicite la carga del nombre de un usuario y pasaremos a un segundo formulario donde mostraremos los datos actuales de dicho usuario. En una tercer página procedemos a modificar los datos ingresados.
import cgi
import wsgiref.handlers

from google.appengine.ext import webapp
from google.appengine.ext import db

class Formulario1(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
<html>
<head></head>
<body>
<form action="formulario2" method="post">
Ingrese nombre de usuario a modificar:
<input type="text" name="nombre"><br>
<input type="submit" value="Buscar"><br>
</form>
</body>
</html>
""")

class TablaUsuarios(db.Model):
  nombre=db.StringProperty()
  clave=db.StringProperty()

class Formulario2(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    nom=cgi.escape(self.request.get('nombre'))
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom)
    usu=usuario.fetch(1)
    if len(usu)>0:
      self.response.out.write("""
<html>
<head></head>
<body>
<form action="procformulario2" method="post">
Nombre actual:
""")
      self.response.out.write("<input type=\"text\" name=\"nombre\" value=\""+usu[0].nombre+"\"><br>")
      self.response.out.write("Clave actual:")
      self.response.out.write("<input type=\"text\" name=\"clave\" value=\""+usu[0].clave+"\"><br>")
      self.response.out.write("<input type=\"hidden\" name=\"nombreoculto\" value=\""+usu[0].nombre+"\">")
      self.response.out.write("""
<input type="submit" value="Modificar"><br>
</form>
</body>
</html>
""")
    else:
      self.response.out.write("No existe un usuario con dicho nombre<br>")
    self.response.out.write("</body></body>")
   

class ProcFormulario2(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    nomoculto=cgi.escape(self.request.get('nombreoculto'))
    nom=cgi.escape(self.request.get('nombre'))
    cla=cgi.escape(self.request.get('clave'))   
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nomoculto)
    usu=usuario.fetch(1)
    if len(usu)>0:
      usu[0].nombre=nom
      usu[0].clave=cla
      usu[0].put()
    else:
      self.response.out.write("No existe un usuario con dicho nombre<br>")
    self.response.out.write("<a href=\"\\\">Principal</a>")     
    self.response.out.write("</body></body>")
   
def main():
  application = webapp.WSGIApplication([('/', Formulario1),
                                        ('/formulario2', Formulario2),
                                        ('/procformulario2', ProcFormulario2),                                       
                                       ],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()
El segundo formulario debemos inicializar los atributos value de los dos controles text para que aparezcan cargados inicialmente con los datos actuales.
Por otro lado también es necesario definir un campo oculto donde almacenar el nombre de usuario actual, ya que si lo modifica no sabremos cual buscar:
class Formulario2(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    nom=cgi.escape(self.request.get('nombre'))
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom)
    usu=usuario.fetch(1)
    if len(usu)>0:
      self.response.out.write("""
<html>
<head></head>
<body>
<form action="procformulario2" method="post">
Nombre actual:
""")
      self.response.out.write("<input type=\"text\" name=\"nombre\" value=\""+usu[0].nombre+"\"><br>")
      self.response.out.write("Clave actual:")
      self.response.out.write("<input type=\"text\" name=\"clave\" value=\""+usu[0].clave+"\"><br>")
      self.response.out.write("<input type=\"hidden\" name=\"nombreoculto\" value=\""+usu[0].nombre+"\">")
      self.response.out.write("""
<input type="submit" value="Modificar"><br>
</form>
</body>
</html>
""")
    else:
      self.response.out.write("No existe un usuario con dicho nombre<br>")
    self.response.out.write("</body></body>")
La tercer página recupera el usuario que ingresó en el primer formulario, pero rescatado del campo oculto. Procedemos seguidamente a modificar los datos rescatados de la tabla y confirmamos los nuevos datos llamando al método put:
class ProcFormulario2(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    nomoculto=cgi.escape(self.request.get('nombreoculto'))
    nom=cgi.escape(self.request.get('nombre'))
    cla=cgi.escape(self.request.get('clave'))   
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nomoculto)
    usu=usuario.fetch(1)
    if len(usu)>0:
      usu[0].nombre=nom
      usu[0].clave=cla
      usu[0].put()
    else:
      self.response.out.write("No existe un usuario con dicho nombre<br>")
    self.response.out.write("<a href=\"\\\">Principal</a>")     
    self.response.out.write("</body></body>")
Listado, Alta, Baja y Modificación (App Engine).
Ahora plantearemos todos los conceptos vistos para el manejo de una tabla de datos utilizando el Google App Engine.
Mostraremos un listado con una tabla con todos los nombres de usuarios y claves, dos hipervínculos uno para poder borrar el usuario y otro para poder modificar el registro. Por último dispondremos un hipervínculo para llamar a un formulario de alta de usuario.
import cgi
import wsgiref.handlers

from google.appengine.ext import webapp
from google.appengine.ext import db

class TablaUsuarios(db.Model):
  nombre=db.StringProperty()
  clave=db.StringProperty()

class Listado(webapp.RequestHandler):
  def get(self):
    self.response.out.write("<html><head></head><body>")
    self.response.out.write("<table border=\"1\">")
    self.response.out.write("<tr>")
   

self.response.out.write("<td>Usuario</td><td>Clave</td><td>Borrar</td><td>Modificar&l

t;/td>") 
    self.response.out.write("</tr>")
    usuarios=db.GqlQuery("select * from TablaUsuarios")
    for usu in usuarios:
      self.response.out.write("<tr>")
      self.response.out.write("<td>" + usu.nombre +"</td>")
      self.response.out.write("<td>" + usu.clave +"</td>")
      self.response.out.write("<td><a href=\"baja?nombre="+usu.nombre+"\">Borra?</a>"+"</td>")
      self.response.out.write("<td><a

href=\"formulariomodificacion?nombre="+usu.nombre+"\">Modifica?</a>"+"</td>")
      self.response.out.write("</tr>")
    self.response.out.write("<tr>")
    self.response.out.write("<td colspan=\"4\"><a href=\"formularioalta\">Alta</a></td>") 
    self.response.out.write("</tr>")  
    self.response.out.write("</table>")  
    self.response.out.write("</body></html>")

class FormularioAlta(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
<html>
<head></head>
<body>
<form action="alta" method="post">
Ingrese su nombre:
<input type="text" name="nombre"><br>
Ingrese su clave:
<input type="password" name="clave"><br>
<input type="submit" value="Alta"><br>
</form>
</body>
</html>
""")

class Alta(webapp.RequestHandler):
  def post(self):
    nom=cgi.escape(self.request.get('nombre'))
    cla=cgi.escape(self.request.get('clave'))
    usuario=TablaUsuarios()
    usuario.nombre=nom
    usuario.clave=cla
    usuario.put()
    self.redirect("/")

class Baja(webapp.RequestHandler):
  def get(self):
    nom=cgi.escape(self.request.get('nombre'))
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom)
    usu=usuario.fetch(1)
    if len(usu)>0:
      usu[0].delete()
    self.redirect("/")
   
class FormularioModificacion(webapp.RequestHandler):
  def get(self):
    self.response.out.write("<html><head></head><body>")
    nom=cgi.escape(self.request.get('nombre'))
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom)
    usu=usuario.fetch(1)
    if len(usu)>0:
      self.response.out.write("""
<html>
<head></head>
<body>
<form action="modificacion" method="post">
Nombre actual:
""")
      self.response.out.write("<input type=\"text\" name=\"nombre\" value=\""+usu[0].nombre+"\"><br>")
      self.response.out.write("Clave actual:")
      self.response.out.write("<input type=\"text\" name=\"clave\" value=\""+usu[0].clave+"\"><br>")
      self.response.out.write("<input type=\"hidden\" name=\"nombreoculto\" value=\""+usu[0].nombre+"\">")
      self.response.out.write("""
<input type="submit" value="Modificar"><br>
</form>
</body>
</html>
""")
    else:
      self.response.out.write("No existe un usuario con dicho nombre<br>")
    self.response.out.write("</body></body>")
   
class Modificacion(webapp.RequestHandler):
  def post(self):
    nomoculto=cgi.escape(self.request.get('nombreoculto'))
    nom=cgi.escape(self.request.get('nombre'))
    cla=cgi.escape(self.request.get('clave'))   
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nomoculto)
    usu=usuario.fetch(1)
    if len(usu)>0:
      usu[0].nombre=nom
      usu[0].clave=cla
      usu[0].put()
    self.redirect("/")

     
def main():
  application = webapp.WSGIApplication([('/', Listado),
                                        ('/formularioalta',FormularioAlta ),
                                        ('/alta',Alta ),                                       
                                        ('/baja', Baja),
                                        ('/formulariomodificacion', FormularioModificacion),
                                        ('/modificacion', Modificacion),                                       
                                       ],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()
En la función main() debemos inicializar la lista que vincula las URL de las páginas y las clases que se ejecutan:
def main():
  application = webapp.WSGIApplication([('/', Listado),
                                        ('/formularioalta',FormularioAlta ),
                                        ('/alta',Alta ),                                       
                                        ('/baja', Baja),
                                        ('/formulariomodificacion', FormularioModificacion),
                                        ('/modificacion', Modificacion),                                       
                                       ],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)
La clase Listado es la que muestra la raiz del sitio y tiene por objetivo crear una tabla HTML con todos los usuarios almacenados en la TablaUsuarios. Además de imprimir cada registro disponemos un hipervínculo pasando como parámetro el nombre de usuario a borrar o modificar:
class Listado(webapp.RequestHandler):
  def get(self):
    self.response.out.write("<html><head></head><body>")
    self.response.out.write("<table border=\"1\">")
    self.response.out.write("<tr>")
   

self.response.out.write("<td>Usuario</td><td>Clave</td><td>Borrar</td><td>Modificar&l

t;/td>") 
    self.response.out.write("</tr>")
    usuarios=db.GqlQuery("select * from TablaUsuarios")
    for usu in usuarios:
      self.response.out.write("<tr>")
      self.response.out.write("<td>" + usu.nombre +"</td>")
      self.response.out.write("<td>" + usu.clave +"</td>")
      self.response.out.write("<td><a href=\"baja?nombre="+usu.nombre+"\">Borra?</a>"+"</td>")
      self.response.out.write("<td><a

href=\"formulariomodificacion?nombre="+usu.nombre+"\">Modifica?</a>"+"</td>")
      self.response.out.write("</tr>")
    self.response.out.write("<tr>")
    self.response.out.write("<td colspan=\"4\"><a href=\"formularioalta\">Alta</a></td>") 
    self.response.out.write("</tr>")  
    self.response.out.write("</table>")  
    self.response.out.write("</body></html>")
La clase FormularioAlta muestra los dos controles text y el botón submit, cuando se presiona dicho botón se procede a llamar a la URL alta:
class FormularioAlta(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
<html>
<head></head>
<body>
<form action="alta" method="post">
Ingrese su nombre:
<input type="text" name="nombre"><br>
Ingrese su clave:
<input type="password" name="clave"><br>
<input type="submit" value="Alta"><br>
</form>
</body>
</html>
""")
La clase Alta inicializa un objeto de la clase TablaUsuarios, procede a registrar los datos y mediante el método redirect redirige a la raiz del sitio (es decir la clase Listado):
class Alta(webapp.RequestHandler):
  def post(self):
    nom=cgi.escape(self.request.get('nombre'))
    cla=cgi.escape(self.request.get('clave'))
    usuario=TablaUsuarios()
    usuario.nombre=nom
    usuario.clave=cla
    usuario.put()
    self.redirect("/")
Cuando se presiona el hipervínculo "Borra?" en el listado se ejecuta la clase Baja y recibe como parámetro en el hipervínculo el nombre de usuario a borrar. Recuperamos el registro, llamamos al método delete y redirigimos nuevamente a la página de listado:
class Baja(webapp.RequestHandler):
  def get(self):
    nom=cgi.escape(self.request.get('nombre'))
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom)
    usu=usuario.fetch(1)
    if len(usu)>0:
      usu[0].delete()
    self.redirect("/")
Cuando se presiona el hipervínculo "Modificación?" se ejecuta la clase FormularioModificacion, en este recuperamos el nombre de usuario e inicializamos los controles text y el campo oculto:
class FormularioModificacion(webapp.RequestHandler):
  def get(self):
    self.response.out.write("<html><head></head><body>")
    nom=cgi.escape(self.request.get('nombre'))
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom)
    usu=usuario.fetch(1)
    if len(usu)>0:
      self.response.out.write("""
<html>
<head></head>
<body>
<form action="modificacion" method="post">
Nombre actual:
""")
      self.response.out.write("<input type=\"text\" name=\"nombre\" value=\""+usu[0].nombre+"\"><br>")
      self.response.out.write("Clave actual:")
      self.response.out.write("<input type=\"text\" name=\"clave\" value=\""+usu[0].clave+"\"><br>")
      self.response.out.write("<input type=\"hidden\" name=\"nombreoculto\" value=\""+usu[0].nombre+"\">")
      self.response.out.write("""
<input type="submit" value="Modificar"><br>
</form>
</body>
</html>
""")
    else:
      self.response.out.write("No existe un usuario con dicho nombre<br>")
    self.response.out.write("</body></body>")
Cuando se presiona el botón modificación del formulario anterior se ejecuta la clase Modificacion donde se procede a modificar el nombre y clave del usuario. Por último se redirige a la raiz del sitio:
class Modificacion(webapp.RequestHandler):
  def post(self):
    nomoculto=cgi.escape(self.request.get('nombreoculto'))
    nom=cgi.escape(self.request.get('nombre'))
    cla=cgi.escape(self.request.get('clave'))   
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nomoculto)
    usu=usuario.fetch(1)
    if len(usu)>0:
      usu[0].nombre=nom
      usu[0].clave=cla
      usu[0].put()
    self.redirect("/")
Si te ha gustado el artículo inscribete al feed clicando en la imagen más abajo para tenerte siempre actualizado sobre los nuevos contenidos del blog:

Guia Python: alta, listado, consulta y borrado de datos (1a parte).

Python es un lenguaje de script desarrollado por Guido van Rossum.

Podemos codificar empleando programación lineal, estructurada y orientada a objetos (tengamos en cuenta que esta última es la que se ha impuesto en la actualidad).

Se cuenta con intérpretes de Python en múltiples plataformas: Windows, Linux, Mac etc. Se pueden desarrollar aplicaciones de escritorio como aplicaciones web. Empresas como Google, Yahoo, Nasa etc. utilizan este lenguaje para sus desarrollos (actualmente el creador de Python Guido van Rossum trabaja para Google.)

Se puede ejecutar instrucciones de Python desde la línea de comando o creando archivos con extensión *.py. Cuando uno comienza a aprender este lenguaje la línea de comandos nos provee una retroalimentación del resultado en forma inmediata.

El objetivo de este tutorial es presentar en forma progresiva los conceptos fundamentales de este lenguaje y poder analizar los problemas resueltos y codificar los problemas propuestos en este mismo sitio, sin tener que instalar en un principio el Python en su equipo (o luego de instalado poder avanzar con el tutorial en cualquier máquina conectada a internet).
python Atributos de una clase
Alta y listado de una base de datos (App Engine)
El almacenamiento de datos utilizando la infraestructura de Google es bastante distinta a las metodologías de MySql, Oracle, Sql Server etc.
Google utiliza una tecnología llamada 'Bigtable', básicamente es un sistema de almacenamiento distribuido que permite escalar de forma muy sencilla, evitando que por ejemplo las consultas de tablas con millones de registros se resientan.

Para hacer uso de esta tecnología debemos importar el paquete db:

from google.appengine.ext import db
 
Desarrollaremos una aplicación que permita almacenar el nombre de usuario y su clave. Luego imprimiremos todos los registros almacenados.
import cgi
import wsgiref.handlers

from google.appengine.ext import webapp
from google.appengine.ext import db

class Formulario1(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
<html>
<head></head>
<body>
<form action="procformulario1" method="post">
Ingrese su nombre:
<input type="text" name="nombre"><br>
Ingrese su clave:
<input type="password" name="clave"><br>
<input type="submit" value="enviar"><br>
</form>
</body>
</html>
""")


class TablaUsuarios(db.Model):
  nombre=db.StringProperty()
  clave=db.StringProperty()

class ProcFormulario1(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    nom=cgi.escape(self.request.get('nombre'))
    cla=cgi.escape(self.request.get('clave'))
    usuario=TablaUsuarios()
    usuario.nombre=nom
    usuario.clave=cla
    usuario.put()
    self.response.out.write("<a href=\"listadousuarios\">Listado</a>")
    self.response.out.write("</body></body>")
   
class ListadoUsuarios(webapp.RequestHandler):
  def get(self):
    self.response.out.write("<html><head></head><body>")
    usuarios=db.GqlQuery("select * from TablaUsuarios")
    for usu in usuarios:
      self.response.out.write("Nombre:" + usu.nombre +"<br>")
      self.response.out.write("Clave:" + usu.clave +"<br>")
      self.response.out.write("<hr>")
    self.response.out.write("<a href=\"\\\">Principal</a>")
    self.response.out.write("</body></body>")

  
   
def main():
  application = webapp.WSGIApplication([('/', Formulario1),
                                        ('/procformulario1', ProcFormulario1),
                                        ('/listadousuarios', ListadoUsuarios)],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()
Veamos todo lo que debemos agregar:

Debemos importar el paquete db:

from google.appengine.ext import db 

Debemos declarar una clase que representa una tabla.

Esta clase debe heredar de la clase Model contenida en el paquete db.

Definimos dos atributos de tipo StringProperty.

StringProperty es una clase contenida en el paquete db y que encapsula el manejo de un campo de cadena de caracteres:

class TablaUsuarios(db.Model): nombre=db.StringProperty() clave=db.StringProperty()

Para efectuar el alta de un registro en la tabla:

class ProcFormulario1(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    nom=cgi.escape(self.request.get('nombre'))
    cla=cgi.escape(self.request.get('clave'))
    usuario=TablaUsuarios()
    usuario.nombre=nom
    usuario.clave=cla
    usuario.put()
    self.response.out.write("<a href=\"listadousuarios\">Listado</a>")
    self.response.out.write("</body></body>")

Creamos un objeto de la clase Tablausuarios:


usuario=TablaUsuarios()

Inicializamos los atributos nombre y clave con los datos extraidos del formulario.

usuario.nombre=nom
    usuario.clave=cla


Llamamos al método put que confirma los datos previamente cargados:

usuario.put() 

Para obtener un listado de todos los registros almacenados:

class ListadoUsuarios(webapp.RequestHandler):
  def get(self):
    self.response.out.write("<html><head></head><body>")
    usuarios=db.GqlQuery("select * from TablaUsuarios")
    for usu in usuarios:
      self.response.out.write("Nombre:" + usu.nombre +"<br>")
      self.response.out.write("Clave:" + usu.clave +"<br>")
      self.response.out.write("<hr>")
    self.response.out.write("<a href=\"\\\">Principal</a>")
    self.response.out.write("</body></body>")



Creamos un objeto de la clase GqlQuery pasando como parámetro al constructor los datos a recuperar:


usuarios=db.GqlQuery("select * from TablaUsuarios")


Mediante un for recorremos la lista de usuarios y los imprimimos:


for usu in usuarios:
      self.response.out.write("Nombre:" + usu.nombre +"<br>")
      self.response.out.write("Clave:" + usu.clave +"<br>")
      self.response.out.write("<hr>")

Como esta aplicación requiere tres páginas luego debemos registrarlas cuando creamos un objeto de la clase WSGIApplication:
def main():
  application = webapp.WSGIApplication([('/', Formulario1),
                                        ('/procformulario1', ProcFormulario1),
                                        ('/listadousuarios', ListadoUsuarios)],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

Consulta de datos (App Engine).

Confeccionaremos una aplicación que nos permita ingresar el nombre de usuario y nos recupere y muestre su clave. Tener en cuenta los datos cargados en el concepto anterior:
import cgi
import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.ext import db
class Formulario1(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
<html>
<head></head>
<body>
<form action="procformulario1" method="post">
Ingrese nombre de usuario:
<input type="text" name="nombre"><br>
<input type="submit" value="enviar"><br>
</form>
</body>
</html>
""")
class TablaUsuarios(db.Model):
  nombre=db.StringProperty()
  clave=db.StringProperty()
class ProcFormulario1(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    nom=cgi.escape(self.request.get('nombre'))
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom)
    usu=usuario.fetch(1)
    if len(usu)>0:
      self.response.out.write("Clave:" + usu[0].clave +"<br>")
    else:
      self.response.out.write("No existe un usuario con dicho nombre<br>")
    self.response.out.write("<a href=\"\\\">Principal</a>")
    self.response.out.write("</body></body>")   
def main():
  application = webapp.WSGIApplication([('/', Formulario1),
                                        ('/procformulario1', ProcFormulario1),
                                       ],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
  main()

Creamos un formulario para ingresar el nombre de usuario a buscar:


class Formulario1(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
<html>
<head></head>
<body>
<form action="procformulario1" method="post">
Ingrese nombre de usuario:
<input type="text" name="nombre"><br>
<input type="submit" value="enviar"><br>
</form>
</body>
</html>
""")


El botón submit hace que se ejecute la clase ProcFormulario1:

class ProcFormulario1(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    nom=cgi.escape(self.request.get('nombre'))
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom)
    usu=usuario.fetch(1)
    if len(usu)>0:
      self.response.out.write("Clave:" + usu[0].clave +"<br>")
    else:
      self.response.out.write("No existe un usuario con dicho nombre<br>")
    self.response.out.write("<a href=\"\\\">Principal</a>")
    self.response.out.write("</body></body>")




Primero generamos una consulta a la tabla y le pasamos como parámetro en el campo nombre el valor rescatado del formulario, debemos utilizar los dos puntos y un uno para indicar que dicho espacio será remplazado por el segundo parámetro:

usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom)


La clase GqlQuery tiene un método llamado fetch que retorna todos los registros generados en la consulta. Al método fetch le pasamos la cantidad de registros que queremos rescatar y por último accedemos a la primer componente de la lista siempre y cuando la cantidad de elementos sea mayor a cero.


Borrado de datos (App Engine).


Confeccionaremos una aplicación que nos permita ingresar el nombre de usuario y efectúe su borrado.. Tener en cuenta los datos cargados en conceptos anterioriores.


import cgi
import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.ext import db

class Formulario1(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
<html>
<head></head>
<body>
<form action="procformulario1" method="post">
Ingrese nombre de usuario a borrar:
<input type="text" name="nombre"><br>
<input type="submit" value="enviar"><br>
</form>
</body>
</html>
""")
class TablaUsuarios(db.Model):
  nombre=db.StringProperty()
  clave=db.StringProperty()
class ProcFormulario1(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    nom=cgi.escape(self.request.get('nombre'))
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom)
    usu=usuario.fetch(1)
    if len(usu)>0:
      usu[0].delete()
      self.response.out.write("Se borro el usuario<br>")
    else:
      self.response.out.write("No existe un usuario con dicho nombre<br>")
    self.response.out.write("<a href=\"\\\">Principal</a>")
    self.response.out.write("</body></body>")

def main():
  application = webapp.WSGIApplication([('/', Formulario1),
                                        ('/procformulario1', ProcFormulario1),
                                       ],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
  main()



Si lo comparamos con la consulta es prácticamente igual con la salvedad donde en lugar de mostrarlo procedemos a borrarlo:


nom=cgi.escape(self.request.get('nombre'))
    usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom)
    usu=usuario.fetch(1)
    if len(usu)>0:
      usu[0].delete()
      self.response.out.write("Se borro el usuario<br>")

    else:
      self.response.out.write("No existe un usuario con dicho nombre<br>")

El método delete borrar el registro.


Si te ha gustado el artículo inscribete al feed clicando en la imagen más abajo para tenerte siempre actualizado sobre los nuevos contenidos del blog:

Guia Python: Formularios HTML.

Python es un lenguaje de script desarrollado por Guido van Rossum.

Podemos codificar empleando programación lineal, estructurada y orientada a objetos (tengamos en cuenta que esta última es la que se ha impuesto en la actualidad).

Se cuenta con intérpretes de Python en múltiples plataformas: Windows, Linux, Mac etc. Se pueden desarrollar aplicaciones de escritorio como aplicaciones web. Empresas como Google, Yahoo, Nasa etc. utilizan este lenguaje para sus desarrollos (actualmente el creador de Python Guido van Rossum trabaja para Google.)

Se puede ejecutar instrucciones de Python desde la línea de comando o creando archivos con extensión *.py. Cuando uno comienza a aprender este lenguaje la línea de comandos nos provee una retroalimentación del resultado en forma inmediata.

El objetivo de este tutorial es presentar en forma progresiva los conceptos fundamentales de este lenguaje y poder analizar los problemas resueltos y codificar los problemas propuestos en este mismo sitio, sin tener que instalar en un principio el Python en su equipo (o luego de instalado poder avanzar con el tutorial en cualquier máquina conectada a internet).
python Funciones con parámetros por defecto1
Formulario HTML - control radio (App Engine).
Realizaremos una aplicación que muestre un formulario con dos controles de tipo text, luego dos controles de tipo radio que indiquen si queremos sumar o restar los valores ingresados en los controles text.
import cgi
import wsgiref.handlers

from google.appengine.ext import webapp

class Formulario1(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
<html>
<head></head>
<body>
<form action="procformulario1" method="post">
Ingrese primer valor:
<input type="text" name="valor1">
<br>
Ingrese segundo valor:
<input type="text" name="valor2">
<br>
<input type="radio" name="radio1" value="suma">sumar
<br>
<input type="radio" name="radio1" value="resta">restar
<br>
<input type="submit" value="operar">
</form>
</body>
</html>
""")


class ProcFormulario1(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    v1=int(self.request.get('valor1'))
    v2=int(self.request.get('valor2'))
    operacion=self.request.get('radio1')
    if operacion=="suma":
      resultado=v1+v2
    else:
      resultado=v1-v2
    self.response.out.write("El resultado de la " + operacion + " es " + str(resultado))
    self.response.out.write("</body></body>")
   
   
def main():
  application = webapp.WSGIApplication([('/', Formulario1),
                                        ('/procformulario1', ProcFormulario1)],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()
En la página principal del sitio asociamos la clase que despliega el formulario HTML:
('/', Formulario1)
Luego la clase que procesa los datos ingresados en el formulario es ProcFormulario1, en esta primero rescatamos los dos valores ingresados en los controles text y procedemos a convertilos a entero:
v1=int(self.request.get('valor1'))
    v2=int(self.request.get('valor2'))
Rescatamos la propiedad value del control radio seleccionado:
operacion=self.request.get('radio1')
Y mediante un if verificamos si tenemos que sumar o restar los contenidos de los text:
if operacion=="suma":
      resultado=v1+v2
    else:
      resultado=v1-v2
Por último procedemos a imprimir el resultado de la operación:
self.response.out.write("El resultado de la " + operacion + " es " + str(resultado))
Formulario HTML - control select (App Engine).
Veamos el control HTML de tipo select. Este tipo de control el funcionamiento es similar al de un conjunto de controles de tipo radio.
Confeccionaremos el mismo problemas del concepto anterior es decir cargar dos números y posteriormente mediante un control de tipo select seleccionar si queremos sumarlos o restarlos (solo una de estas operaciones se puede elegir)
La sintaxis del control de tipo select es:
<select name="operacion">
<option value="suma">Sumar</option>
<option value="resta">Restar</option>
</select>
Es importante notar que la sintaxis es bastante distinta a los controles de tipo text y radio.
El elemento select tiene definido la propiedad name mediante la cual rescataremos el valor seleccionado en el servidor.
El elemento select contiene un conjunto de elementos option. Cada elemento option tiene definido la propiedad value. El que quede seleccionado el control select rescata su propiedad value.
Luego el programa en Python utilizando Google App Engine:
import cgi
import wsgiref.handlers

from google.appengine.ext import webapp

class Formulario1(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
<html>
<head></head>
<body>
<form action="procformulario1" method="post">
Ingrese primer valor:
<input type="text" name="valor1">
<br>
Ingrese segundo valor:
<input type="text" name="valor2">
<br>
<select name="operacion">
<option value="suma">Sumar</option>
<option value="resta">Restar</option>
</select>
<br>
<input type="submit" value="operar">
</form>
</body>
</html>
""")

class ProcFormulario1(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    v1=int(self.request.get('valor1'))
    v2=int(self.request.get('valor2'))
    op=self.request.get('operacion')
    if op=="suma":
      resultado=v1+v2
    else:
      resultado=v1-v2
    self.response.out.write("El resultado de la " + op + " es " + str(resultado))
    self.response.out.write("</body></body>")
   

   
def main():
  application = webapp.WSGIApplication([('/', Formulario1),
                                        ('/procformulario1', ProcFormulario1)],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()
De forma similar como venimos trabajando en una clase desplegamos el formulario HTML (Formulario1) y otra clase procesa el contenido del formulario (ProcFormulario1).
En la página que procesamos los datos del formulario rescatamos los valores de los controles text y los convertimos a entero:
v1=int(self.request.get('valor1'))
    v2=int(self.request.get('valor2'))
Seguidamente rescatamos la propiedad name de la opción seleccionada del control select:
op=self.request.get('operacion')
Mediante un if verificamos si tenemos que sumar o restar
if op=="suma":
      resultado=v1+v2
    else:
      resultado=v1-v2
Por último mostramos el resultado:
self.response.out.write("El resultado de la " + op + " es " + str(resultado))

Formulario HTML - control select con selección múltiple (App Engine).
Veamos una variante del control select la cual permite seleccionar varias opciones de su contenido. Para esto debemos agregar la propiedad multiple cuando lo definimos:
<select name="operacion" multiple>
Con este simple cambio podemos seleccionar más de un elemento del interior del control select.
Confeccionaremos el mismo problema anterior, solo que ahora podremos seleccionar las dos operaciones en forma simultanea:
import cgi
import wsgiref.handlers

from google.appengine.ext import webapp

class Formulario1(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
<html>
<head></head>
<body>
<form action="procformulario1" method="post">
Ingrese primer valor:
<input type="text" name="valor1">
<br>
Ingrese segundo valor:
<input type="text" name="valor2">
<br>
<select name="operacion" multiple>
<option value="suma">Sumar</option>
<option value="resta">Restar</option>
</select>
<br>
<input type="submit" value="operar">
</form>
</body>
</html>
""")


class ProcFormulario1(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    v1=int(self.request.get('valor1'))
    v2=int(self.request.get('valor2'))
    operaciones=self.request.get_all('operacion')
    for op in operaciones:
      if op=="suma":
        resultado=v1+v2
        self.response.out.write("El resultado de la " + op + " es " + str(resultado) + "<br>")   
      if op=="resta":
        resultado=v1-v2
        self.response.out.write("El resultado de la " + op + " es " + str(resultado) + "<br>")
    self.response.out.write("</body></body>")
   
   
def main():
  application = webapp.WSGIApplication([('/', Formulario1),
                                        ('/procformulario1', ProcFormulario1)],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()
Para recuperar la lista de valores seleccionados del control select debemos llamar al método get_all del objeto request en lugar de get:
operaciones=self.request.get_all('operacion')
Luego mediante una estructura repetitiva recorremos la lista de valores devuelto y comparamos con los valores posibles:
for op in operaciones:
      if op=="suma":
        resultado=v1+v2
        self.response.out.write("El resultado de la " + op + " es " + str(resultado) + "<br>")   
      if op=="resta":
        resultado=v1-v2
        self.response.out.write("El resultado de la " + op + " es " + str(resultado) + "<br>")

Formulario HTML - control checkbox (App Engine).
Otra forma de hacer selecciones múltiples es utilizar un conjunto de controles de tipo checkbox. Cada control de tipo checkbox es independiente.
Resolvamos el problema del concepto anterior empleando dos controles de tipo checkbox:
import cgi
import wsgiref.handlers

from google.appengine.ext import webapp

class Formulario1(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
<html>
<head></head>
<body>
<form action="procformulario1" method="post">
Ingrese primer valor:
<input type="text" name="valor1">
<br>
Ingrese segundo valor:
<input type="text" name="valor2">
<br>
<input type="checkbox" name="check1" value="suma">sumar
<br>
<input type="checkbox" name="check2" value="resta">restar
<br>
<input type="submit" value="operar">
</form>
</body>
</html>
""")


class ProcFormulario1(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    v1=int(self.request.get('valor1'))
    v2=int(self.request.get('valor2'))
    su=self.request.get('check1')
    if su=="suma":
       resultado=v1+v2
       self.response.out.write("El resultado de la " + su + " es " + str(resultado) + "<br>")   
    re=self.request.get('check2')
    if re=="resta":
       resultado=v1-v2
       self.response.out.write("El resultado de la " + re + " es " + str(resultado) + "<br>")   
    self.response.out.write("</body></body>")

     
def main():
  application = webapp.WSGIApplication([('/', Formulario1),
                                        ('/procformulario1', ProcFormulario1)],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()
Cada checkbox lo recuperamos en forma independiente:
su=self.request.get('check1')
    if su=="suma":
       resultado=v1+v2
       self.response.out.write("El resultado de la " + su + " es " + str(resultado) + "<br>")   
Si se encuentra seleccionado el método get retorna el valor de la propiedad value del control HTML, en caso de no estar seleccionado retorna un string vacío.

Alta y listado de una base de datos (App Engine).
El almacenamiento de datos utilizando la infraestructura de Google es bastante distinta a las metodologías de MySql, Oracle, Sql Server etc.
Google utiliza una tecnología llamada 'Bigtable', básicamente es un sistema de almacenamiento distribuido que permite escalar de forma muy sencilla, evitando que por ejemplo las consultas de tablas con millones de registros se resientan.
Para hacer uso de esta tecnología debemos importar el paquete db:
from google.appengine.ext import db
Desarrollaremos una aplicación que permita almacenar el nombre de usuario y su clave. Luego imprimiremos todos los registros almacenados.
import cgi
import wsgiref.handlers

from google.appengine.ext import webapp
from google.appengine.ext import db

class Formulario1(webapp.RequestHandler):
  def get(self):
    self.response.out.write("""
<html>
<head></head>
<body>
<form action="procformulario1" method="post">
Ingrese su nombre:
<input type="text" name="nombre"><br>
Ingrese su clave:
<input type="password" name="clave"><br>
<input type="submit" value="enviar"><br>
</form>
</body>
</html>
""")

class TablaUsuarios(db.Model):
  nombre=db.StringProperty()
  clave=db.StringProperty()

class ProcFormulario1(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    nom=cgi.escape(self.request.get('nombre'))
    cla=cgi.escape(self.request.get('clave'))
    usuario=TablaUsuarios()
    usuario.nombre=nom
    usuario.clave=cla
    usuario.put()
    self.response.out.write("<a href=\"listadousuarios\">Listado</a>")
    self.response.out.write("</body></body>")
   
class ListadoUsuarios(webapp.RequestHandler):
  def get(self):
    self.response.out.write("<html><head></head><body>")
    usuarios=db.GqlQuery("select * from TablaUsuarios")
    for usu in usuarios:
      self.response.out.write("Nombre:" + usu.nombre +"<br>")
      self.response.out.write("Clave:" + usu.clave +"<br>")
      self.response.out.write("<hr>")
    self.response.out.write("<a href=\"\\\">Principal</a>")
    self.response.out.write("</body></body>")
    
def main():
  application = webapp.WSGIApplication([('/', Formulario1),
                                        ('/procformulario1', ProcFormulario1),
                                        ('/listadousuarios', ListadoUsuarios)],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()
Veamos todo lo que debemos agregar:
  • Debemos importar el paquete db:
    from google.appengine.ext import db
    Debemos declarar una clase que representa una tabla. Esta clase debe heredar de la clase Model contenida en el paquete db. Definimos dos atributos de tipo StringProperty. StringProperty es una clase contenida en el paquete db y que encapsula el manejo de un campo de cadena de caracteres:
  • class TablaUsuarios(db.Model): nombre=db.StringProperty() clave=db.StringProperty()
  • Para efectuar el alta de un registro en la tabla:


class ProcFormulario1(webapp.RequestHandler):
  def post(self):
    self.response.out.write("<html><head></head><body>")
    nom=cgi.escape(self.request.get('nombre'))
    cla=cgi.escape(self.request.get('clave'))
    usuario=TablaUsuarios()
    usuario.nombre=nom
    usuario.clave=cla
    usuario.put()
    self.response.out.write("<a href=\"listadousuarios\">Listado</a>")
    self.response.out.write("</body></body>")


Creamos un objeto de la clase Tablausuarios:


usuario=TablaUsuarios()


Inicializamos los atributos nombre y clave con los datos extraidos del formulario.


usuario.nombre=nom
    usuario.clave=cla




Llamamos al método put que confirma los datos previamente cargados:


usuario.put()
  • Para obtener un listado de todos los registros almacenados:
class ListadoUsuarios(webapp.RequestHandler):
  def get(self):
    self.response.out.write("<html><head></head><body>")
    usuarios=db.GqlQuery("select * from TablaUsuarios")
    for usu in usuarios:
      self.response.out.write("Nombre:" + usu.nombre +"<br>")
      self.response.out.write("Clave:" + usu.clave +"<br>")
      self.response.out.write("<hr>")
    self.response.out.write("<a href=\"\\\">Principal</a>")
    self.response.out.write("</body></body>")

Creamos un objeto de la clase GqlQuery pasando como parámetro al constructor los datos a recuperar:

usuarios=db.GqlQuery("select * from TablaUsuarios")

Mediante un for recorremos la lista de usuarios y los imprimimos:


for usu in usuarios:
      self.response.out.write("Nombre:" + usu.nombre +"<br>")
      self.response.out.write("Clave:" + usu.clave +"<br>")
      self.response.out.write("<hr>")


Como esta aplicación requiere tres páginas luego debemos registrarlas cuando creamos un objeto de la clase WSGIApplication:


def main():
  application = webapp.WSGIApplication([('/', Formulario1),
                                        ('/procformulario1', ProcFormulario1),
                                        ('/listadousuarios', ListadoUsuarios)],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)




Si te ha gustado el artículo inscribete al feed clicando en la imagen más abajo para tenerte siempre actualizado sobre los nuevos contenidos del blog: