xpanel, lxde, linux, fbpanel opensuse, linux, instalacion gtk3, gnome, ambienti grafici PS3, mandos, Play Station, Linux edubuntu, ubuntu, linux fedora, linux, discapacitados visuales fuduntu, fedora, ubuntu, linux, distribuciones inkscape, grafica, linux, editor tux, tuz, iconos, mascota, linux artistx, distro, linux, artistas, graficos

Psicoacustica:

Primero hay que ser claros sobre algunos conceptos como acústica, psicoacústica y el conocimiento básico del proceso de audición.Acústica es “una ciencia interdisciplinaria que trata el estudio de todas las ondas mecánicas en gases líquidos y solidos, incluyendo vibraciones, sonido, ultrasonido e infrasonido”.  Esta se divide en múltiples ramas y una de ellas es la psicoacustica que es el estudio científico de la percepción del sonido, esto significa las respuestas psicologicas y fisiológicas asociadas con el sonido.

 

Como deben saber el sonido es una forma de energía que se mueve a través de un medio en ondas de presión, y el oído es un órgano sensitivo que reconoce las ondas de presión y las convierte en impulsos nerviosos, ya que es el cerebro y el sistema nervioso central el que “escucha”.

 

Las ondas de sonido son percibidas por el cerebro a través de la activación de las células nerviosas en la porción auditiva del sistema nervioso central. El oído transforma las ondas de presión de sonido del mundo exterior en señales en forma de impulsos nerviosos que son enviados al cerebro, es por esto que el cerebro juega un papel importante en todo el proceso. Para resumir el oído puede ser visto como un transductor con analizador de espectro que permite percibir variaciones de frecuencia y energía.

Psicoacústica y Efecto Haas2. Efecto Haas:

Este fenómeno psicoacústico describe como el oído humano percibe una fuente de sonido, identificando la dirección del sonido reflejado dado el tiempo que toma en llegar al oído. Este efecto lo trabajo Helmut Haas en la universidad de Gottingen, Gottingen, Alemania. Un experimento simple para la comprensión del fenómeno es escuchar dos señales iguales usando auriculares estéreo, donde una de las señales se encuentre ligeramente retardada con respecto a la otra.

 

Las Etapas del Experimento se ilustran a continuación:

Nota: El oído es más sensible a un 1 KHz por lo que el experimento se realiza a esa frecuencia. Para entender esto consulta sobre el umbral de audición.

• Aplicando una señal de un tono en ambos parlantes como se ve en la figura 1: en este caso el sonido es percibido como una fuente en dirección del Angulo bisector creado entre ambos parlantes (en caso de audífonos, la fuente se siente al frente).

Aplicando un tono a parlantes estéreo

• Aplicando una señal de un tono en ambos parlantes, retardando la señal en uno de ellos entre 5 y 30 milisegundos respecto a la otra como se ve en la Figura 2: en este caso solo se percibe una fuente con el doble de intensidad en la dirección del parlante no retardado (en caso de audífonos, la fuente se siente a un lado).  Este mismo efecto puede ser generado variando la intensidad de la señal en cada uno de los parlantes, esto se conoce como paneo.

Tono aplicado a parlantes estero con retardo

• Aplicando una señal de un tono en ambos parlantes, retardando la señal en uno de ellos mas de 35 milisegundos respecto a la otra como se ve en la Figura 3: en este caso el sonido retardado es percibido como un eco del primero pero de fuentes diferentes (en caso de audífonos, se sienten dos fuentes diferentes a cada lado).

Tono aplicado a parlantes estero con retardo mayor a 35ms

De esta manera el fenómeno caracteriza el retardo experimentado en espacios acústicos y da una idea de cómo es la suma la energía del sonido del oído.

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:

0

1.  Retardo simple o Single Delay

Single delay es la base de varios efectos de audio. El Delay puede ser percibido en espacios acústicos como la reflexión de una onda sonora que se sobre pone sobre el sonido de la fuente. La distancia con la fuente determina el retardo de cada onda reflejada.

 

El resultado de la suma de la señal original con la reflejada hace que el efecto sea audible. Los parámetros manipulables para este efecto son:

T: Tiempo del retardo.

g: La amplitud de la señal retardada.

Los Efectos basados en retardos se pueden dividir en dos:

 

Single Delay.
Delay Modulation.

Slapback Delay
Vibrato

Echo
Flanger

Multi-Tap Delay
Chorus

Hay dos representaciones para el delay y para mejor compresión de estos en su implementación digital es necesario conocer el filtro peine.

Single Delay y filtro Peine

 

2.   Filtro Peine

El Filtro Peine funciona sumando una señal retardada a la señal original, creando interferencia constructiva o destructiva. Este se presenta por ejemplo cuando dos parlantes reproducen la misma señal a distancias diferentes el oyente. Dada la longitud de onda y la diferencia de distancias entre parlantes y oyente, la señal puede llegar con diferente fase presentando interferencia. Básicamente cuando el sonido indirecto tomo un camino más largo que el directo, se presenta un filtro peine cuando ambos sonidos se combinan.

Existen dos configuraciones del filtro peine, de respuesta Finita (FIR) y de respuesta Infinita (IIR).

 

2.1.    Filtro Peine de Respuesta Finita (FIR)

Este produce una serie finita de respuestas. Esto se da porque la señal va por un lazo directo por lo cual al detenerse las respuestas retardadas cesan.

Diagrama de Bloques Filtro Peine FIR

La ecuación diferencial y la función de transferencia:

y(n) = x(n) + g*x(n-m)

m=t/fs : fs es la frecuencia de muestreo

H(z) = 1+g*Z^-m = (Z^m + g)/Z^m

Analizando la respuesta en frecuencia de la figura 1 . se puede ver que para valores positivos de g  el filtro amplifica las frecuencias pares múltiplos de 1/t  y atenúa las impares.

Figure 2. respuesta en frecuencia (magnitud y fase) con t= 8 y g=2

También se aprecia que la magnitud permanece entre 20Log10(1+g)  y 20Log10(1-g) . Por la serie de picos y similitud con un peine es que recibe su nombre.

La distribución de las raíces y los zeros se pueden ver en la siguiente figura donde el patrón de distribución es equivalente en cada plano.

Diagrama de polos y zeros, Filtro Peine FIR.

2.2.    Filtro Peine de Respuesta Infinita (IIR) .

Este produce una serie inacabable de respuestas. Esto se debe a que la señal de entrada circula por un lazo de realimentación afectado por un Delay como se ve en la Figura 4. Cada ves que la señal atraviesa del delay es atenuada por g.

Figura 4. Diagrama de Bloques Filtro Peine IIR

La ecuación diferencial y la función de transferencia:

y(n) = x(n) + g*y(n-m)

m = t/fs :fs es la frecuencia de muestreo

H(z) = 1/(1 – g*Z^-m) = Z^m/(Z^m – g)

Analizando la respuesta en frecuencia de la figura 4 . se aprecia que para valores positivos de g, el filtro atenua las frecuencias impares múltiplos de 1/t y amplifica las pares. También la magnitud se encuentra entre   La amplitud de la señal resultante es gp donde p es el número de ciclos que la señal a cruzado por el delay. Es por esto que g debe ser menor que 1 ya que el sistema es inestable y cumpliendo con esta condición se mantiene estable.

Figura 5. respuesta en frecuencia (magnitud y fase) con t= 8 y g=2

La distribución de las raíces y los zeros se pueden ver en la siguiente figura muestra con claridad la inestabilidad del sistema. es por esto que |g|<1 para mantener la condición de estabilidad de otra forma la señal crecería sin fin.

Diagrama de polos y zeros, Filtro Peine IIR}

1.1.    Filtro Peine Universal

Dado que el oído percibe diferente el delay entre  50 a 100ms o más y entre 30ms o menos, diversas sensaciones pueden ser creadas jugando solo entre esos rangos es por esto que con una misma configuración de bloques se pueden crear los siguientes efectos.

Filtro Peine Universal con Delay variable

Como se puede ver en la Figura 7 este diagrama de bloques representa una configuración universal ya que cuenta con el lazo directo FIR y el lazo de retroalimentación IIR como también con un oscilador de baja frecuencia que permite variar el tiempo de retardo permitiendo crear diferentes efectos de acuerdo a los parámetros para cada uno.

Los parámetros manipulables son:

Gain: Ganancia directa señal original

FF-G: ganancia de lazo directo.

FB-G: ganancia de retroalimentación

A: Delay de Off-set, es el retardo sobre el cual se genera la oscilación.

Depth: amplitud del oscilador

Rate: Frecuencia del oscilador

Teniendo en cuenta lo anterior y asumiendo lo enunciado por el efecto Hass se plantean los siguientes efectos.

Diagrama de bloques Eco

Gain

FF G

FB G

Delay

Depth

Rate

Echo

1

0-1

0-1

>100ms

0

0

Diagrama de bloques Vibrato

Gain

FF G

FB G

Delay

Depth

Rate

Vibrato

0

0-1

0

5-10ms

0-2.5ms

5-15Hz

Diagrama de bloques Flanger

Gain

FF G

FB G

Delay

Depth

Rate

Flanger

1

0-1

0-1

<15ms

0.3-14.7ms

0.5-5Hz

 Diagrama de bloques Chorus

Gain

FF G

FB G

Delay

Depth

Rate

Chorus

1

0-1

0-1

20-30ms

0-5ms

0.2-2Hz

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:

0
Cambio de Programa (0xC0~0xCF).

La palabra programa es el conjunto de parámetros que definen la generación de sonidos en un sintetizador. El mensaje de cambio de programa sirve para cambiar el sonido de un instrumento, pero puede ser usado para otros fines diferentes. Este cambio de sonido es en relación de un sonido preestablecido con otro, no un medio de ajustar parámetros individuales del circuito generador de sonidos. Un mensaje de cambio de programa esta compuesto de 2 bytes: uno de encabezamiento seguido de un byte de datos con un rango entre 0×00~0x7f.

 

Cambio en la altura (Pitch Wheel) (0xE0~0xEF).

Los mensajes de modificación del pitch permiten cambiar la altura gradual y suavemente entre notas. De esta forma se puede aumentar la resolución microtonalmente, superando la barrera del semitono. Estos mensajes contienen tres bytes. El byte de encabezamiento lleva el código del mensaje y el número del canal. Los dos bytes siguientes son el valor de modificación del pitch. Los grupos de siete bits en ambos bytes se unen para formar un valor de 14 bits. El primer byte contiene los siete bits menos significativos, y el segundo los siete más significativos. En decimal, un número de 14 bits equivale a un rango entre 0 y 16383, permitiendo un control en el pitch muy fino. Usualmente el valor 8192 se utiliza como punto cero, y los valores por encima de este significan incremento en el pitch, y un decremento los valores por debajo del mismo valor.

 

portmidi

  • Crear un proyecto de tipo consola con el nombre midi.
  • Dentro de la carpeta en la que se creó el proyecto, aparece una carpeta con el nombre midi, donde se encuentran los archivos con el código fuente. Dentro de esta carpeta se deben agregar los siguientes archivos que se encuentran en el proyecto Pormedia:
    • porttime.h: se encuentra en la carpeta porttime.
    • porttime.lib: se encuentra en la carpeta porttime\Release
    • portmidi.h: se encuentra en la carpeta pm_common.
    • portmidi.dll: se encuentra en la carpeta Release.
    • portmidi.lib: se encuentra en la carpeta Release.
  • Agregar los archivos porttime.h y portmidi.h al proyecto en Visual Studio.
  • En la pestaña Solution Explorer, hacer clic derecho sobre el nombre del proyecto y seleccionar Properties.
  • En Configuration Properties seleccionar Linker y luego Input.
  • En Additional Dependencies, agregar las siguientes líneas:
    • winmm.lib
    • porttime.lib
    • portmidi.lib
  • Para verificar que funciona correctamente, en el main, agregar el método Pm_Initialize(); y compilar.
  • Recursos

MIDI-OX

The MIDI Manufacturers Association (MMA)

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:

0
Presión de pulsación polifónica (0xA0~0xAF).

Algunos fabricantes llaman a este mensaje “aftertouch”. Aplicar presión a una tecla después de haber sido presionada produce un mensaje de aftertouch. Similar a la estructura de los mensajes de nota encendida y apagada, el primer byte de datos es el numero de nota, y el segundo es la presión aplicada a la misma.

 

La presión en modo polifónico es muy deseable pues permite una gran flexibilidad en la interpretación de secuencias MIDI. Si el controlador es compatible con aftertouch polifónico entonces cada tecla individual puede enviar su propio mensaje de aftertouch. Si el controlador sólo es compatible con aftertouch monofónico, entonces si la presión se aplica a cualquier tecla, una señal de aftertouch se envía para todo el controlador.

Una aplicación de este mensaje es para introducir efectos de modulación en el sintetizador, sin necesidad de que usar simultaneamente un controlador de modulación (el cual generalmente es un rueda, o un controlador tipo ribbon).

 

Cambio en controlador (0xB0~0xBF).

La mayoría de los mensajes MIDI son de naturaleza específica, pero los mensajes de cambio en controlador son una excepción. Este tipo de mensaje también se le llama CC ó continuous controller. Se puede emplear para alterar cualquier parametro que el diseñador del equipo desee. Puede ser un parámetro del generador de sonidos, como el tiempo de ataque, la forma de la envolvente ó parámetros más generales como el nivel de volumen. No hay una verdadera estandarización de todos los controladores continuos, aunque hay algunas convenciones sobre su uso.

 

Los números de controlador entre 0×00 y 0x1f (0 a 31 decimal), son controladores continuos que poseen valores de control (el tercer byte) entre 0×00 y 0x7f (0 a 127 decimal). En este rango se encuentran los controladores de aliento, potenciómetros de volumen, modulación,etc. Los números de controlador entre 0×20 a 0x3f, se emplean opcionalmente para enviar los 7 bits menos significativos extras para los controladores entre 0×00 y 0x1f si se requiere de una resolución muy alta. Los números de controlador del 0×40 al 0x5f (64 al 95) son controladores de conmutación, como los pedales de sustain, portamento, e interruptores on/off en general. El tercer byte tiene un valor de 0×00 para indicar un estado de apagado (off) y de 0x7f (127 decimal) para indicar un estado de encendido (on). Los números de controlador de 0×60 a 0×79 (96 a 121) son indefinidos, y los de 0x7a a 0x7f (122 a 127) están reservados para mensajes de modalidad de canal. Inicialmente no se necesitaba que se asignaran los números de controlador a un controlador físico específico, con la excepción del mando de modulación el cual se sugería que fuese asignado al número 0×01. Más adelante se estandarizaría esta práctica y se definirían otros controladores en posiciones específicas como el volumen en 0×07 y el sustain en 0×40.

midi controladores

 

Lista de controladores

0×00 Selección de banco

0×01 Rueda de modulación

0×02 Controlador de aliento

0×03 Sin definir

0×04 Controlador de pie

0×05 Tiempo de portamento

0×06 Entrada de datos

0×07 Volumen principal

0×08 Balance

0×09 Sin definir

0x0a Panorama (Pan)

0x0b Expresión

0x0c Control de efecto 1

0x0d Control de efecto 2

0x0e Sin definir

0x0f Sin definir

0×10~0×13 Propósito general

0×14~0x1f Sin definir

0×20~0x3f LSB para cambios de controladores en el rango de 0×00 a 0x1f donde se necesite más resolución

0×40 Pedal de Damper/Sustain

0×41 Portamento

0×42 Sostenuto

0×43 Pedal de suavizado (Soft)

0×44 Pedal de Legato

0×45 Hold 2

0×46 Variación de sonido/Excitador

0×47 Contenido Armónico/Compresor

0×48 Tiempo de liberación (Release Time)/Distorsión

0×49 Tiempo de ataque/Ecualizador

0x4a Brillo/Expansor (Compuerta) (Expander(Gate))

0x4b Sin definir/Reverberación

0x4c Sin definir/Retardo (Delay)

0x4d Sin definir/Transposición de tono (Pitch transpose)

0x4e Sin definir/ Flanger ó Chorus

0x4f Sin definir/ Efecto Especial

0×50~0×53 Propósito general

0×54 Control de Portamento

0×55~0x5a Sin definir

0x5b Profundidad del efecto (Efecto 1)

0x5c Profundidad de trémolo (Efecto 2)

0x5d Profundidad del Chorus (Efecto 3)

0x5e Profundidad del celeste (Efecto 4)

0x5f Profundidad del phaser (Efecto 5)

0×60 Incremento de datos

0×61 Incremento de datos

0×62 Número de Párametro no Registrado LSB

0×63 Número de Párametro no Registrado MSB

0×64 Número de Párametro Registrado LSB

0×65 Número de Párametro Registrado MSB

0×66~0×77 Sin definir

0×78 Todo el sonido apagado

0×79 Reiniciar todos los controladores

0x7a Control local

0x7b Todas las notas apagadas

0x7c Modo Omni Apagado

0x7d Modo Omni Encendido

0x7e Modo Mono Encendido

0x7f Modo Poly Encendido

midi teclas8

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:

0
Implementación en el hardware.

El diseño original se desarrolló después de una serie de reuniones que celebraron los principales fabricantes de instrumentos musicales de Japón y Estados Unidos. El diseño del circuito de control permite la transmisión de datos de un instrumento a otro, o de un computador a un instrumento. El procesador necesario para manejar los mensajes es de 8 bits que se transmiten en serie. Esta decisión se tomó en base a la relación costo/beneficio. La transmisión en paralelo posibilitaría que los 8 bits se transmitieran simultaneamente, aumentando la velocidad de transmisión, pero con ello el numero de lineas que necesitarían estar conectadas debería ser de al menos 8, y por tanto el costo de producción también aumentaría.

 

En la transmisión en serie solo se emplean dos lineas: en una se envían los bits de datos uno detrás del otro, y en la otra el dispositivo receptor avisa al emisor si hay errores de paridad en la corriente de datos. Así que la transmisión en serie fue elegida a pesar de ser más lenta que la paralela, porque tenía la ventaja de usar un conector más sencillo y de ser mucho mas barata, pues el índice de comercialización fue pensado en una gama de precios asequible a la mayoría de usuarios de computadores personales y músicos que empleasen sintetizadores y máquinas de ritmos de la época.

 

La velocidad de transmisión es de 3125 palabras en serie (Words) por segundo, esto es 31.25 Kbaudios. Dicha velocidad es 38.5% veces más rápida que una interface RS232 que hasta su tercera revisión (C), permite oficialmente una transmisión cercana a los 20000 baudios, concretamente a 1920 palabras por segundo (aunque los chips de interface en un PC habilitan hasta 115200 baudios si el cableado no es muy largo). La velocidad de reloj de 31.25 Kbaudios es relativamente elevada con respecto a la transmisión en serie, pero no es lo suficientemente rápida como veremos más adelante, cuando expliquemos en detalle la anatomía de los mensajes MIDI.

 

Un mensaje MIDI tiene 10 bits transmitidos por cada byte. La transmisión de un mensaje de 3 bytes dura aproximadamente 1 milisegundo. Debido a que MIDI se transmite en forma serial, es muy probable que dos o más eventos musicales que ocurran simultaneamente al ser enviados uno detrás de otro, no se reproduzcan exactamente en el mismo instante en el receptor. Sin embargo esto es lo suficientemente rápido como para que esos eventos se perciban como simultáneos, aunque a nivel numérico no ocurra así. En un teclado MIDI, al tocar simultaneamente 10 teclas, no se percibe latencia, ya que la transmisión total de este evento dura unos 10 ms. Esto lo explicó el medico alemán Helmut Haas en su tesis doctoral en 1949 así: ¨si varios sonidos independientes llegan a nuestro cerebro en un intervalo inferior a 50 ms éste los fusiona y los interpreta como uno sólo¨.

 

MIDI se transmite de forma asincrónica, por lo cual ha de definirse cada byte para el instrumento receptor. Para ello se emplea un chip ACIA (Asynchronous Communications Interface Adaptor) como el Motorola 6850, que agrega dos bit extas a cada byte del instrumento maestro. Empieza con ¨0¨, como un bit de arranque (start) , seguido de los 8 bits de datos en serie y termina en ¨1¨, llamado el bit final (stop). Esta palabra de 10 bits se transmite al instrumento receptor, donde un segundo chip ACIA, lo vuelve a convertir nuevamente en los ocho bits de los datos reales.

 

El chip ACIA, esta protegido dentro del circuito por optoaislamiento. Un optoaislador es un dispositivo que usa celdas fotoeléctricas para permitir que dos circuitos no conectados intercambien señales, permaneciendo eléctricamente aislados. En el caso ilustrado a continuación, el aislamiento lo proporciona el IC Sharp PC-900.

midi_complex_setup

Mensajes MIDI.

Anteriormente explicabamos que un mensaje MIDI tiene 10 bits transmitidos en serie. Los 8 bits intermedios forman el byte MIDI, del cual existen dos tipos: bytes de estado (status bytes) y bytes de datos (data bytes). Dentro de la estructura del mensaje MIDI, el byte de estado es tambien llamado byte de encabezamiento, puesto que es el que se transmite primero .Todos los bytes de estado tienen el valor del bit más significativo en ¨1¨. De esta manera, los bytes de estado comienzan en 10000000 y terminan en 11111111. En hexadecimal, es el rango comprendido desde 0×80 (128 decimal) hasta 0xFF (255 decimal).

 

Como consecuencia, solo tres bits del cuarteto mas significativo están disponibles para indicar el tipo de mensaje. Esto significa que hay un límite de 8 tipos de mensajes diferentes: 7 mensajes de canal (channel messages), cuyo intervalo comprende entre 0×80 y 0xEF (entre 128 y 239 decimal), y los mensajes exclusivos de sistema (sysex messages), limitados entre 0xF0 y 0xFF.

 

Esto también significa que todos los bytes de data quedan limitados al intervalo entre 0×00 y 0x7F (entre 0 y 127 decimal), puesto que este es el rango en el cual el bit mas significativo tiene el valor “0″.

 

Un byte de data siempre esta precedido de otro byte de data, o de un byte de estado. Dicho de otra forma, todos los mensajes MIDI son transmitidos en este orden: primero un byte de estado, seguido de uno ó dos bytes de datos. La excepción a esta estructura es la de los mensajes exclusivos del sistema, donde puede existir un contenido indefinido de bytes y estos mismos difieren de los bytes de data normales en que su rango esta entre 0×00 y 0xFF (entre 0 y 255 decimal).

 

midi1Mensajes de Canal.

El byte de estado o encabezamiento se divide en 2 cuartetos (fragmentos de cuatro bits). El cuarteto más significativo, es decir los bits del quinto al octavo que se transmiten, lleva el código de identificación del mensaje que se transmite, el cual le indica al receptor que debe hacer: encender una nota, apagarla, elevar el volumen, cambiar gradualmente la altura de la nota (pitch bending),etc.

 

Los bits del primero al cuarto forman el cuarteto menos significativo, y almacenan el numero de canal para el cual se transmite el mensaje. Este numero comprende entre 0×0 y 0xF, es decir entre 0 y 15 decimal. Por convención la numeración de canales es de 1 al 16 y el rango binario de 0 a 15. Esto quiere decir que al canal 1 se le identifica con 0×0, al canal 2 con 0×1, al 3 con 0×2, etc.

 

Nota Apagada (0×80~0x8F) y Nota Encendida (0×90~0x9F)

 

Estos son los dos mensajes MIDI mas importantes. Ambos son mensajes de 3 bytes, característica que comparten con los mensajes de Presión de pulsación polifónica (0xAch) y Cambio en controlador (0xBch).

 

La estructura básica es muy similar. De hecho la unica diferencia entre ambos mensajes, se halla en el código almacenado en el cuarteto de bit mas significativo del byte de estado o encabezamiento. Este primer byte está en el intervalo de 0×90 a 0x9F para el mensaje de activación de nota para los canales 1 al 16, y de forma similar entre 0×80~0x8F para el mensaje de desactivación de nota para cada canal.

 

El primer byte de datos almacena el número de la nota. El Do central, lleva el numero 0x3C (60 decimal) y por lo tanto todos los Do, son múltiplos de 0x0C (12 decimal). Un teclado de piano estandar de 88 notas (8 octavas), va desde 0×15 hasta 0x6C (21 a 108 decimal). El rango de datos entre 0×00 y 0x7F (0 a 127 decimal) da una cobertura de mas de 10 octavas, lo cual es bastante amplio, ya que no todos los instrumentos MIDI tienen un rango tan amplio. Algunos instrumentos simplemente ignoran los mensajes que se salen de su rango de cobertura. Otros transportan la nota a una octava cercana que pueda producir un resultado audible.

 

El segundo byte de datos lleva el valor de la velocidad, la cual es una medida de la fuerza con la que se pulsó la nota en el instrumento. Esta medida puede ser tomada por la tecla de un piano, el pad de una bateria electrónica, o algún otro tipo de controlador MIDI. Generalmente, el diseño de hardware MIDI incluye como responder a sensibilidad generada por el tacto. Esta característica esta ausente en muchos de los primeros instrumentos MIDI, ó en cierto tipo de controladores especializados como los Surface Controllers usados por las estaciones de audio digital modernas. Cuando no se incluye esta característica, se usa 0×40 (64 decimal) ó 0x7F (127 decimal) en los mensajes de activación de nota y 0×00 en los de desactivación.

 

El byte de velocidad controla el volumen de cada nota, pero el diseñador del receptor puede usar este valor también para afectar otro parametro como por ejemplo el tiempo de ataque de la nota.

 

El mensaje de desactivación de nota funciona de forma similar al de activación. A lo largo de los años ha existido una discusión porque parece ser un mensaje redundante, como veremos mas adelante. Sin embargo, existe un modo en que los instrumentos MIDI operan polifónicamente, en el que este mensaje cobra mas sentido. En este modo, el receptor recibe e interpreta en el canal seleccionado, los mensaje emitidos por cualquier canal. De esta manera, se pueden desactivar todas las notas, no importan del canal que provengan, pero para ello debemos ser específicos, en cuanto a cual nota estamos desactivando y con que velocidad.

 

Estado Actual (Running Status).

Cuando los datos MIDI son transmitidos por un secuenciador, en un momento determinado puede llegar a existir un gran número de eventos que deban reproducirse de forma simultánea. En estos casos el retardo introducido por la transmisión de datos en serie puede llegar a ser claramente perceptible. Para ayudar a reducir la cantidad de datos transmitidos MIDI, se emplea una técnica denominada Running Status.

 

Esta técnica toma en consideración el hecho de que es muy habitual que en una cadena de mensajes consecutivos, todos sean del mismo tipo. Por ejemplo, al tocar varios acordes, se generan un montón de mensajes Note On consecutivos, a los que siguen el montón de datos Note Off correspondientes. El truco consiste en que un byte de estado nuevo sólo es enviado si es diferente que el byte de estado que se envió inmediatamente antes. En otras palabras, se emite el byte de estado cuando el mensaje correspondiente no es del mismo tipo que el mensaje inmediatamente anterior (en un mismo canal ).Sólo se transmiten los bytes de datos para todos los mensajes del mismo tipo.

 

La efectividad de esta técnica mejora mucho más si en vez de enviar mensajes Note Off, se envían mensajes Note On con un valor de velocidad igual a 0 (técnica utilizada, por ejemplo, en el secuenciador Logic Audio). De esta forma se producen largas cadenas de mensajes Note On, de transmisión más rápida que las originales cadenas cortas compuestas por mensajes de distintos tipos.

basic-midi-connections1

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:

0

La música y las ciencias exactas guardan una relación que es conocida desde hace siglos. En la antigua Grecia, Pitágoras encontró relaciones entre los sonidos y el peso de martillos de herrero, al tratar de averiguar porque parecían sonar de forma melodiosa al golpearlos con un yunque. Descubrió que un martillo de la mitad de un peso de otro producía un sonido de exactamente el doble de frecuencia que el otro, es decir una octava mas alto.

 

En la Edad Media, los compositores llenaban las catedrales con el sonido de las misas y motetes que estaban proporcionadas ritmica y numericamente con el mismo nivel de precisión de las propias catedrales. A menudo la música era tan compleja que se creia que solo los oídos de Dios podían apreciar las relaciones numéricas, mientras los mortales escuchaban la música.

 

Cualquiera que haya presenciado un concierto, habrá observado que los músicos cuentan 1,2,3,4 ó 1,2,3 antes de comenzar a tocar.

 

Por un lado, la informática se ha ido extendiendo a todos los campos del conocimiento humano. Por otro, la música por si misma, esta fuertemente relacionada con las matemáticas. Asi que fue muy natural que ambos mundos se superpusieran para expandirse. Una aplicación de esta unión, es lo que hoy conocemos como MIDI.

midi

 

Que es MIDI.

MIDI es un acrónimo de Musical Instrument Digital Interface, que significa Interface Digital para Instrumentos Musicales. Fue desarrollado a principios de los años ochenta, como consecuencia de los avances en la música electrónica de esa época.

 

 

El estándar MIDI fue inicialmente propuesto por Dave Smith, presidente de la compañía Sequential Circuits en un documento dirigido a la Audio Engineering Society en 1981. Las primera especificación fue publicada en agosto de 1983 y desde entonces han cambiado poco.

 

Se han realizado algunas pequeñas modificaciones en forma de sutiles adiciones al código MIDI original. En cuanto al hardware que emplea MIDI, hoy en dia muchos dispositivos como controladores, sintetizadores, módulos generadores e interfaces multitrack, son prácticamente impensables sin implementación MIDI.

 

Ya que la tecnologia de hardware ha cambiado, hoy encontramos nuevas formas y puertos para transmitir mensajes MIDI, mas allá de la especificación original. Muchos dispositivos todavía incluyen la implementación de la interface original, en forma de un puerto con conexión DIN hembra de 5 patas a 180 grados. Otros implementan el protocolo a través de un puerto Ethernet, WIFI, USB o Firewire. Finalmente, existen dispositivos ¨híbridos¨, que pueden tener, por ejemplo, puertos MIDI de entrada y salida, al igual que un puerto USB que proporciona conexión directa con el computador.

 

Sin embargo, esto va más alla de la conexión fisica. Hoy MIDI está no sólo en los instrumentos musicales y computadoras. Está en los teléfonos celulares, y muchos otros productos de empresas conocidas como Microsoft, Apple, Nokia, Sony, Yamaha, y otros cientos de empresas de productos de consumo.

 

La música grabada más popular está escrita e interpretada con teclados electrónicos equipados con MIDI (también conocido como “sintetizadores”). Mucha música también se escribe en equipos que utilizan “secuenciadores” y/o “estaciones de trabajo de audio digital”. Otros instrumentos musicales MIDI también se puede utilizar, incluyendo los tambores digitales, guitarras digitales, instrumentos de viento, y mucho más.

Su computador probablemente tiene la capacidad de reproducir archivos MIDI utilizando un sintetizador de software que responde a los mensajes MIDI, y con un adaptador desde su máquina se pueden conectar otros dispositivos MIDI para que pueda usarlos para crear música.

 

Incluso bandas sonoras de películas y televisión suelen ser creadas en instrumentos MIDI. Con los avances en el muestreo digital, tecnologías de síntesis, y en la fabricación y programación de instrumentos musicales digitales, con un sonido cada vez más realistas, cada vez es más probable que la orquesta tocando detrás de un gran éxito de taquilla en la pantalla grande, sea el producto de unos pocos MIDI dispositivos que de docenas de instrumentos acústicos.

 

Además de la creación de música y reproducción descritas anteriormente, MIDI tiene otros usos interesantes y populares. MIDI Show Control es un conjunto diferente de los mensajes MIDI, y es usado ​​para el control y funcionamiento en eventos y parques temáticos.

midi-setup

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:

0

Las etapas son: Instalar Java (OpenJDK), instalar SDK, descargar Targets, verificar los PATHS, crear una aplicación, compilar con $ ant, crear un Android Virtual Device (AVD), arrancar el AVD, compilar la app en el AVD con $ adb install

Nota Importante: no he logrado hacer los PATH absolutos entonces en algunos casos me toca ejecutar las aplicaciones desde el directorio donde se encuentran con el prefijo ./

Empiezo:

Instalo OpenJDK siguiendo ‘https://help.ubuntu.com/community/Java’

Instalo Android SDK siguiendo ‘http://developer.android.com/sdk/installing/index.htm’

Voy al directorio donde instale Android y busco el subdirectorio /tools y ejecuto:

 

$ ./android

android prof

 

Me abre una GUI, descargo el Target Android 4.1

 

Crear un nuevo proyecto desde lìnea de comando: ‘http://developer.android.com/tools/projects/projects-cmdline.htm’

ejemplo de linea para crear una app:

$ ./android create project –target 1 –path ./myFirstAndroid –activity myFirtsAndroidActivity –package com.example.myandroid

 

noto que hay que configurar un Android Virtual Device AVD, leo la explicación de cómo usarlo desde linea de comando:‘http://developer.android.com/tools/devices/managing-avds-cmdline.html’

creo un AVD haciendo desde el directorio /tools:

 

$ ./android create avd -n my_android1.5 -t 1

 

inicio el emulador con:

$ ./emulator @my_android1.5

 

Voy a hace la primera app, siguiendo este tutorial ‘http://developer.android.com/training/basics/firstapp/index.html’

y ahi se ve mi aplicación diciendo Hello World. :D

 

Algunos problemas que se me presentaron:

    me dice que no tengo Targets, encuentro esta respuesta:‘http://stackoverflow.com/questions/1671462/android-can-not-find-a-target’
    al intentar compilar con adb me dice que no encuentra el programa y debo agregarlo a los PATH (ruta) de mi sistema operativo .. según entiendo debo decirle a mi sistema operativo que cuando en alguna terminal se escriba adb el vaya a buscar la aplicación que reside en /plataform-tools. Encuentro esta ayuda:‘http://www.codecoffee.com/tipsforlinux/articles/11.html’
    y esta otra explica como habilitar un PATH con el comando export:‘http://www.cyberciti.biz/faq/unix-linux-adding-path/’

$export PATH=$PATH:~/code/android-sdk-linux/platform-tools
$export PATH=$PATH:~/code/android-sdk-linux/
$export PATH=$PATH:~/code/android-sdk-linux/tools

     Me salio este error por no tener el AVD

* daemon not running. starting it now on port 5037 *
* daemon started successfully *not found
- waiting for device -

busco como funciona el Android Emulator en :‘http://developer.android.com/tools/help/emulator.html’

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:

0
Plantillas – Templates
No es una buena idea codificar el HTML directamente en las vistas.
Es mucho más limpio y más fácil de mantener separar el diseño de la página del código Python. Podemos hacer esto con el sistema de plantillas de Django.

Base del Sistema de Plantillas
Una plantilla de Django es una cadena de texto para separar la presentación de un documento de sus datos. Una plantilla define contenedores y varios bits de lógica básica (etiquetas) que regulan la forma en que el documento debe ser mostrado. Por lo general las plantillas se utilizan para producir HTML, pero las plantillas Django plantillas son igualmente capaces de generar cualquier otro formato basado en texto.

Comencemos con una plantilla sencilla de ejemplo. Esta plantilla Django describe una página HTML que, da las gracias a una persona por hacer un pedido a la empresa.
django logo
<html>
<head><title>Ordering notice</title></head>
<body>
<h1>Ordering notice</h1>
<p>Dear {{ person_name }},</p>
Thanks for placing an order from {{ company }}. It’s scheduled to
ship on {{ ship_date|date:”F j, Y” }}.
Here are the items you’ve ordered:
<ul>
{% for item in item_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% if ordered_warranty %}
Your warranty information will be included in the packaging.
{% else %}
You didn’t order a warranty, so you’re on your own when
the products inevitably stop working.
{% endif %}
Sincerely,
{{ company }}
Esta plantilla es HTML básico con algunas variables y etiquetas de plantilla dentro de ella. Cualquier texto rodeado por un par de llaves (por ejemplo, {{ person_name }}) es una variable. Esto significa “insertar el valor de la variable con el nombre dado.” ¿Cómo podemos especificar los valores de las variables?Llegaremos a eso después.
Cualquier texto que está rodeado de llaves y porcentaje (por ejemplo, {% if ordered_warranted %}) es una etiqueta de plantilla. La definición de una etiqueta es bastante amplia: una etiqueta sólo le dice al sistema de plantillas “haz algo”.
Por último, el segundo párrafo de esta plantilla contiene un ejemplo de filtro, que es la forma más conveniente de modificar el formato de una variable. En este ejemplo, {{ ship_date | date: “F j, Y” }}, estamos pasandole a la variable ship_date el filtro date, dándole al filtro date el argumento “F j, Y”. El formato de filtro date formatea las fechas a un formato dado, como se especifica en el argumento. Los filtros son adjuntados con un carácter de canalización (|).

Cada plantilla Django tiene acceso a varias etiquetas y filtros incorporados, muchos de los cuales serán discutidos en las siguientes secciones.

Usando el sistema de plantillas.
Entremos en el sistema de plantillas de Django para que cómo funciona, pero no estamos todavía para integrarlo con las vistas que hemos creado en el capítulo anterior. Nuestro objetivo aquí es mostrar cómo funciona el sistema independiente del resto de Django. (Por lo general vamos a usar el sistema de plantillas dentro de una vista de Django, pero hay que dejar claro que el sistema de plantillas es sólo una librería de Python que se puede utilizar en cualquier lugar, no sólo en las vistas de Django.)

Esta es la forma más básica en que se puede utilizar el sistema de plantillas de Django:
  1. Crear un objeto Template proporcionando el código de la plantilla raw como una cadena.
  2. Llamar al método render () del objeto Template con un conjunto de variables (el contexto). Esto devuelve una plantilla renderizada completamente como una cadena, con todas las variables y etiquetas de plantilla evaluadas de acuerdo al contexto.
>>> from django import template
>>> t = template.Template(‘My name is {{ name }}.’)
>>> c = template.Context({‘name’: ‘Adrian’})
>>> print t.render(c)
My name is Adrian.
>>> c = template.Context({‘name’: ‘Fred’})
>>> print t.render(c)
My name is Fred.

Crear objetos Template
 La forma más fácil de crear un objeto Template es crear una instancia directamente. La clase Template reside en el módulo django.template, y el constructor toma un argumento, el código de plantilla raw.
Veamos algunos aspectos básicos del sistema de plantillas:
>>> from django.template import Template
>>> t = Template(‘My name is {{ name }}.’)
>>> print t
Si lo estamos haciendo de forma interactiva, veremos algo como esto:
<django.template.Template object at 0xb7d5f24c>

Cuando se crea un objeto Template, el sistema de plantillas compila el código de la plantilla raw internamente de forma optimizada, preparándolo para el renderizado. Pero si el código de la plantilla incluye cualquier error de sintaxis, la llamada a Template() producirá una excepción TemplateSyntaxError.

Renderizar un Template.
django_templates
Una vez que tiene un objeto Template, puede pasarle datos, dándole un contexto. Un contexto es simplemente un conjunto de nombres de variables de plantilla y sus valores asociados. Una plantilla usa un contexto para rellenar sus variables y evaluar sus etiquetas.

Un contexto es representado en Django por la clase Context, que reside en el módulo django.template. Su constructor toma un argumento opcional: un diccionario que mapea los nombres de variables a los valores de las variables. Llamar al método render() del objeto Template con el contexto para rellenar la plantilla:
>>> from django.template import Context, Template
>>> t = Template(‘My name is {{ name }}.’)
>>> c = Context({‘name’: ‘Stephane’})
>>> t.render(c)
u’My name is Stephane.’
Debemos señalar aquí que el valor de retorno de t.render(c) es un objeto Unicode – no una cadena Python normal.  Django utiliza objetos Unicode en lugar de cadenas normales en todo el framework.

He aquí un ejemplo de compilar y renderizar una plantilla, usando una plantilla similar a la ejemplo del principio de este capítulo:
>>> from django.template import Template, Context
>>> raw_template = “”"
Dear {{ person_name }},

… <p>Thanks for placing an order from {{ company }}. It’s scheduled to
… ship on {{ ship_date|date:”F j, Y” }}.</p>

… {% if ordered_warranty %}
… <p>Your warranty information will be included in the packaging.</p>
… {% else %}
… <p>You didn’t order a warranty, so you’re on your own when
… the products inevitably stop working.</p>
… {% endif %}

… <p>Sincerely, <br/>{{ company }} <p> “”"
>>> t = Template(raw_template)
>>> import datetime
>>> c = Context({‘person_name’: ‘John Smith’,
… ‘company’: ‘Outdoor Equipment’,
… ‘ship_date’: datetime.date(2009, 4, 2),
… ‘ordered_warranty’: False})
>>> t.render(c)
u” <p>Dear John Smith,</p>nn<p>Thanks for placing an order from Outdoor Equipment. It’s scheduled tonship on April 2, 2009.</p>nnn<p>You didn’t order a warranty, so you’re on your own whennthe products inevitably stop working.</p>nnn<p>Sincerely,Outdoor Equipment</p>”
  1. Primero importamos las clases Template y Context, ambas residen en el módulo django.template.
  2. Guardamos el texto raw de nuestra plantilla en la variable raw_template. Tenga en cuenta que usamos comillas triples para designar a la cadena, ya que se extiende por varias líneas, por contra, las cadenas entre comillas sencillas no pueden ser envueltas en varias líneas.
  3. A continuación creamos un objeto plantilla, t, pasando raw_template al constructor de la clase Template.
  4. Importamos el módulo de fecha y hora de la librería estándar de Python, porque la necesitaremos en la siguiente declaración.
  5. Creamos un objeto Context, c. El constructor de Context, toma un diccionario Python, que mapea los nombres de variable a los valores. Aquí, por ejemplo, se especifica que persona_name es ‘John Smith’, company es ‘Outdoor Equipment “, y así sucesivamente.
  6. Por último, llamamos al método render () de nuestro objeto plantilla, pasándole el contexto. Esto devuelve la plantilla renderizada, es decir, que reemplaza las variables de la plantilla con los valores actuales de las variables, y ejecuta cualquier etiqueta de la plantilla.
Esos son los fundamentos del uso del sistema de plantillas de Django: simplemente escribir una cadena de plantilla, crear un objeto Template, crear un Context, y llamar al método render().

Múltiples contextos, misma plantilla.
Una vez que tiene un objeto Template, usted puede renderizar múltiples contextos a través de él. Considere este ejemplo:
>>> from django.template import Template, Context
>>> t = Template(‘Hello, {{ name }}’)
>>> print t.render(Context({‘name’: ‘John’}))
Hello, John
>>> print t.render(Context({‘name’: ‘Julie’}))
Hello, Julie
>>> print t.render(Context({‘name’: ‘Pat’}))
Hello, Pat
Cada vez que usted está utilizando la misma plantilla para renderizar múltiples contextos, es más eficiente crear el objeto plantilla una vez, y luego llamar a render() sobre él varias veces:
# Bad
for name in (‘John’, ‘Julie’, ‘Pat’):
t = Template(‘Hello, {{ name }}’)
print t.render(Context({‘name’: name}))
# Good
t = Template(‘Hello, {{ name }}’)
for name in (‘John’, ‘Julie’, ‘Pat’):
print t.render(Context({‘name’: name}))

Búsqueda de variable de Contexto.
En los ejemplos hasta ahora, hemos pasado valores simples a los contextos – en su mayoría cadenas, además de un datetime.date. Sin embargo, el sistema de plantillas maneja estructuras de datos complejas, tales como listas, diccionarios, y objetos personalizados.

La clave para atravesar estructuras complejas de datos en las plantillas Django es el carácter de punto (.). Utilice un punto para acceder a las claves del diccionario, atributos, métodos, o índices de un objeto.
Por ejemplo, supongamos que usted está pasando un diccionario Python a una plantilla. Para acceder a los valores de ese diccionario por clave de diccionario, use el punto:
>>> from django.template import Template, Context
>>> person = {‘name’: ‘Sally’, ‘age’: ’43′}
>>> t = Template(‘{{ person.name }} is {{ person.age }} years old.’)
>>> c = Context({‘person’: person})
>>> t.render(c)
u’Sally is 43 years old.’
Del mismo modo, los puntos también permiten el acceso a los atributos de los objetos. Por ejemplo, un objeto datetime.date de Python tiene atributos año, mes, día, y puede utilizar un punto para acceder a esos atributos en una plantilla Django:
>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(1993, 5, 2)
>>> d.year
1993
>>> d.month
5
>>> d.day
2
>>> t = Template(‘The month is {{ date.month }} and the year is {{ date.year }}.’)
>>> c = Context({‘date’: d})
>>> t.render(c)
u’The month is 5 and the year is 1993.’
Este ejemplo utiliza una clase personalizada, lo que demuestra que los puntos permiten también el acceso a atributos de objetos arbitrarios:
>>> from django.template import Template, Context
>>> class Person(object):
def __init__(self, first_name, last_name):
self.first_name, self.last_name = first_name, last_name
>>> t = Template(‘Hello, {{ person.first_name }} {{ person.last_name }}.’)
>>> c = Context({‘person’: Person(‘John’, ‘Smith’)})
>>> t.render(c)
u’Hello, John Smith.’
Los puntos también puede hacer referencia a métodos de objetos. Por ejemplo, cada cadena Python tiene los métodos upper() y isdigit(), y usted puede llamarlos en las plantillas Django, usando la misma sintaxis del punto:
>>> from django.template import Template, Context
>>> t = Template(‘{{ var }}—{{ var.upper }}—{{ var.isdigit }}’)
>>> t.render(Context({‘var’: ‘hello’}))
u’hello—HELLO—False’
>>> t.render(Context({‘var’: ’123′}))
u’123—123—True’
Tenga en cuenta que no se incluyen los paréntesis en las llamadas a métodos. Además, no es posible pasar argumentos a los métodos, sólo puede llamar a métodos que no requieren argumentos.
Por último, los puntos también se utilizan para acceder a los índices de lista, como en este ejemplo:
>>> from django.template import Template, Context
>>> t = Template(‘Item 2 is {{ items.2 }}.’)
>>> c = Context({‘items’: ['apples', 'bananas', 'carrots']})
>>> t.render(c)
u’Item 2 is carrots.’
Las búsquedas de puntos se pueden resumir así: cuando la plantilla se encuentra con un punto en un nombre de variable, trata las búsquedas siguientes, en este orden:
  • Diccionario (por ejemplo, foo["bar"])
  • Atributo (por ejemplo, foo.bar)
  • Llamada a método (por ejemplo, foo.bar())
  • Índice de Lista (por ejemplo, foo[2])
El sistema utiliza el tipo de búsqueda que funciona primero. Es una falta de lógica del circuito.

Las búsquedas del punto se pueden anidar varios niveles de profundidad. Por ejemplo, el ejemplo siguiente utiliza {{ person.name.upper() }}, que se traduce en una búsqueda de diccionario (person['name']) y luego
una llamada al método (upper()):
>>> from django.template import Template, Context
>>> person = {‘name’: ‘Sally’, ‘age’: ’43′}
>>> t = Template(‘{{ person.name.upper }} is {{ person.age }} years old.’)
>>> c = Context({‘person’: person})
>>> t.render(c)
u’SALLY is 43 years old.
Comportamiento de llamada a método.
Las llamadas a los métodos son un poco más complejas que el de otros tipos de búsqueda. Aquí hay algunas cosas a tener en cuenta.
Si, durante la búsqueda de métodos, un método produce una excepción, la excepción se propagará a menos que la excepción tenga un atributo silent_variable_failure a True. Si la excepción tiene un atributo silent_variable_failure, la variable se renderizará como una cadena vacía, como en este ejemplo:
>>> t = Template(“My name is {{ person.first_name }}.”)
>>> class PersonClass3:
def first_name(self):
raise AssertionError, “foo”
>>> p = PersonClass3()
>>> t.render(Context({“person”: p}))
Traceback (most recent call last):

AssertionError: foo
>>> class SilentAssertionError(AssertionError):
… silent_variable_failure = True
>>> class PersonClass4:

def first_name(self):

raise SilentAssertionError
>>> p = PersonClass4()
>>> t.render(Context({“person”: p}))
u’My name is .’
Una llamada al método sólo funcionará si el método no requiere argumentos. De lo contrario, el el sistema se moverá al siguiente tipo de búsqueda (índice de lista).
Obviamente, algunos métodos tienen efectos colaterales y sería absurdo, y, posiblemente, incluso un agujero de seguridad, permitir al sistema de plantillas acceder a ellos. Digamos, por ejemplo, que tiene un objeto BackAccount que tiene un método delete(). Si una plantilla incluye algo como {{ account.delete() }}, donde account es un objeto BankAccount, el objeto sería eliminado al procesar la plantilla. Para evitar esto, establezca el atributo de función alters_data en el método:
def delete(self):
# Delete the account
delete.alters_data = True
El sistema de plantillas no ejecutará cualquier método marcado de esta manera. Continuando con el ejemplo actual, si una plantilla incluye {{ account.delete }} y el método delete() tienen alters_data = True, entonces el método delete() no se ejecutará cuando la plantilla se renderice. En su lugar, se producirá un error silencioso.

¿Cómo se gestionan las variables inválidas?
Por defecto, si una variable no existe el sistema de plantillas la renderiza como una cadena vacía, error silencioso. Considere este ejemplo:
¡
>>> from django.template import Template, Context
>>> t = Template(‘Your name is {{ name }}.’)
>>> t.render(Context())
u’Your name is .’
>>> t.render(Context({‘var’: ‘hello’}))
u’Your name is .’
>>> t.render(Context({‘NAME’: ‘hello’}))
u’Your name is .’
>>> t.render(Context({‘Name’: ‘hello’}))
u’Your name is .’
Jugar con objetos Context.
La mayoría de las veces, usted instanciará objetos Context pasando un diccionario totalmente lleno a Context(). Pero usted también puede añadir y eliminar elementos de un objeto Context, una vez instanciado,usando la sintaxis estándar de Python diccionario:
>>> from django.template import Context
>>> c = Context({“foo”: “bar”})
>>> c['foo']
‘bar’
>>> del c['foo']
>>> c['foo']
Traceback (most recent call last):

KeyError: ‘foo’
>>> c['newvariable'] = ‘hello’
>>> c['newvariable']
‘hello’
Etiquetas y Filtros de Plantilla Básica.
Etiquetas.
if / else
La etiqueta {% if %} evalúa una variable, y si esa variable es True (es decir, que existe, no está vacío, y no es un valor boolean FALSE), el sistema mostrará todo entre {% if %} y {% endif %}, como en este ejemplo:
{% if today_is_weekend %}
Welcome to the weekend!
{% endif %}
Una etiqueta {% else %} es opcional:
{% if today_is_weekend %}
Welcome to the weekend!
{% else %}
Get back to work.
{% endif %}
for
La etiqueta {% for %} permite un bucle sobre cada elemento de una secuencia. La plantilla renderizará todo entre {% for %} y {% endfor %}.
Por ejemplo, podría utilizar el siguiente ejemplo para mostrar una lista de atletas dada una variable athlete_list:
<ul> {% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
y al revés:
{% for athlete in athlete_list reversed %}

{% endfor %}
Es posible anidar etiquetas {% for %}.
La etiqueta for soporta una clausula opcional {% empty %} que le permite definir que salida si la lista está vacía.
{% for athlete in athlete_list %}
{{ athlete.name }}
{% empty %}
There are no athletes. Only computer programmers.
{% endfor %}
No hay soporte para opciones del tipo break y continue.
Dentro de cada bucle {% for %} usted puede acceder a una variable llamada forloop. Esta variable tiene algunas características que le dan información sobre el progreso del bucle:
  • forloop.counter siempre se establece en un número entero que representa el número de veces que se ha entrado en el bucle.
  • forloop.counter0 es como forloop.counter, excepto que es indexado en cero. Su valor será fijado a 0 la primera vez que se entre en el bucle.
  • forloop.revcounter siempre se establece en un número entero que representa el número de elementos restantes del bucle.
  • forloop.revcounter0 es como forloop.revcounter, excepto que es indexado en cero.
  • forloop.first es un valor booleano que se establece a True si esta es la primera iteración del bucle.
  • forloop.last es un valor booleano que se establece a True si esta es la última iteración del bucle.
  • forloop.parentloop es una referencia al objeto forloop del bucle padre, en caso de bucles anidados.
ifequal / ifnotequal
La etiqueta {% ifequal %} compara dos valores y muestra todo entre {% ifequal %} y {% endifequal %} si los valores son iguales. Este ejemplo compara la plantilla de las variables user y currentuser:
{% ifequal user currentuser %}
<h1>Welcome!</h1>
{% endifequal %}
Al igual que {% if %} la etiqueta {% ifequal %} soporta un {% else %} opcional:
{% ifequal section ‘sitenews’ %}
<h1>Site News</h1>
{% else %}
<h1>No News Here</h1>
{% endifequal %}
Sólo las variables de plantilla, cadenas, enteros y números decimales se permiten como argumentos para {% ifequal %}. Estos son ejemplos válidos:
{% ifequal variable 1 %}
{% ifequal variable 1.23 %}
{% ifequal variable ‘foo’ %}
{% ifequal variable “foo” %}
Cualquier otro tipo de variables, tales como diccionarios, listas o booleanos no pueden codificarse en la etiqueta {% ifequal %}. Estos son ejemplos inválidos:
{% ifequal variable True %}
{% ifequal variable [1, 2, 3] %}
{% ifequal variable {‘key’: ‘value’} %}
Si necesita testear si algo es verdadero o falso, use {% if %} en lugar de {% ifequal %}.
Comentarios
Para designar un comentario usar {# #}.
No pueden usar esta sintaxis para varias líneas. Para ello usar la etiqueta {% comment %}, como esto:
{% comment %}
This is a
multiline comment.
{% endcomment %}
Filtros
Los filtros de plantilla son formas sencillas de alterar el valor de las variables antes de renderizarlas. Los filtros utilizan un carácter de canalización (pipe), como esto:
{{ name|lower }}
Los filtros se pueden encadenar, es decir, que pueden ser usados en conjunto de manera que la salida de un filtro se aplica al siguiente. He aquí un ejemplo que convierte el primer elemento de una lista a mayúsculas:
{{ my_list|first|upper }}
Algunos filtros toman argumentos que vienen después de dos puntos y siempre entre comillas dobles. He aquí un ejemplo:
{{ bio|truncatewords:”30″ }}
Esto muestra las primeras 30 palabras de la variable bio.
Los siguientes son algunos de los filtros más importantes:
  • addslashes: Agrega una barra invertida antes de que cualquier barra invertida, comillas simples o comillas dobles. Esto es útil si el texto producido se incluye en una cadena JavaScript.
  • date: Formatea una cadena de fecha o fecha/hora de acuerdo a un formato dado como parámetro.
  • length: Devuelve la longitud del valor. Para una lista, devuelve el número de elementos. Para una cadena, devuelve el número de caracteres. Funciona en cualquier objeto Python que sabe cómo determinar su propia longitud, es decir, cualquier objeto que tiene un método __len__()
Filosofías y limitaciones
Ahora que usted tiene una idea del sistema de plantillas de Django, hay que señalar alguna de sus limitaciones intencionales, junto con algo de filosofía de por qué funciona de la forma en que funciona.

Más que cualquier otro componente de las aplicaciones web, la sintaxis de las plantillas es muy subjetiva, y las opiniones de los programadores varían significativamente.

Con esto en mente, es posible que le interese saber que Django no requiere que usted use su lenguaje de plantillas. Debido a que Django está destinado a ser un completo entorno web que proporcione todas las piezas necesarias para los desarrolladores web para ser productivo, muchas veces es más conveniente el uso del sistema de plantillas de Django que otras librerías de plantillas Python, pero no es un requisito estricto en ningún sentido.

Sin embargo, está claro que tenemos una fuerte preferencia por el lenguaje de plantillas de Django. El sistema de plantillas tiene sus raíces en la forma en que el desarrollo web se hace en el mundo en línea combinado con la experiencia de los creadores de Django. Aquí están algunas de nuestras filosofías:

  • La lógica de negocio deben estar separada de la lógica de presentación. Los desarrolladores de Django ven el sistema de plantillas como una herramienta que controla la presentación y la lógica relacionada con la presentación, y eso es todo.
  • La sintaxis debe estar desacoplada del HTML/XML. Aunque el sistema de plantillas de Django se utiliza principalmente para producir HTML, su intención es ser tan útil para los formatos no HTML, tales como el texto sin formato.

  • Los diseñadores se supone que se sienten cómodos con el código HTML. El sistema de plantillas no está diseñado de manera que las plantillas necesariamente se muestran muy bien en los editores WYSIWYG como Dreamweaver. Django espera que los autores de plantillas estén cómodos editando el HTML directamente.
  • Se asume que los diseñadores no son programadores de Python. Los autores del sistema de plantillas reconocen que a menudo las plantillas de las páginas web son escritas por los diseñadores, no por programadores, y por lo tanto no se debe asumir el conocimiento de Python.
  • El objetivo no es inventar un lenguaje de programación. El objetivo es ofrecer como mucho la funcionalidad del esquema de programación, tal como la ramificación y la iteración, que es esencial para la toma de decisiones relacionadas con la presentación.
    Recordemos la vista current_datetime en mysite.views. Esto es:
    from django.http import HttpResponse
    import datetime
    def current_datetime(request):
    now = datetime.datetime.now()
    html = “It is now %s.” % now
    return HttpResponse(html)
    Vamos a cambiar esta vista para utilizar el sistema de plantillas de Django. Al principio se podría pensar en hacer algo como esto:
    from django.template import Template, Context
    from django.http import HttpResponse
    import datetime
    def current_datetime(request):
    now = datetime.datetime.now()
    t = Template(“It is now {{ current_date }}.”)
    html = t.render(Context({‘current_date’: now}))
    return HttpResponse(html)
    Está claro que utiliza el sistema de plantillas, pero no resuelve los problemas que hemos señalado. A saber, la plantilla está incrustada en el código Python, por lo que no se logra una verdadera separación de los datos y la presentación. Vamos a arreglar esto poniendo la plantilla en un archivo separado, que cargará esta vista.
    En primer lugar, podría considerar la posibilidad de guardar la plantilla en algún lugar de su sistema de ficheros y usar Python para leer el contenido de la plantilla. Esto es lo que podría parecerse, suponiendo que la plantilla se ha guardado en el archivo /home/djangouser/templates/mytemplate.html:
    from django.template import Template, Context
    from django.http import HttpResponse
    import datetime
    def current_datetime(request):
    now = datetime.datetime.now()
    # Simple way of using templates from the filesystem.
    # This is BAD because it doesn’t account for missing files!
    fp = open(‘/home/djangouser/templates/mytemplate.html’)
    t = Template(fp.read())
    fp.close()
    html = t.render(Context({‘current_date’: now}))
    return HttpResponse(html)
    Este enfoque, sin embargo, es poco elegante, por estas razones:
    • No maneja el caso de que el archivo falle, como se señala en el código. Si el archivo mytemplate.html no existe o no es legible, la llamada open() lanzará una excepción IOError.
    • Codifica a pelo la ubicación de la plantilla. Si usted fuera a utilizar esta técnica para cada función de vista, estaría duplicando las localizaciones de la plantilla – por no mencionar que se trata de escribir mucho.
    • Incluye una gran cantidad de código repetitivo aburrido. Tienes cosas mejores que hacer que escribir las llamadas a open(), fp.read(), y fp.close() cada vez que se carga una plantilla.
    Para resolver estos problemas, vamos a utilizar la carga de plantillas y la herencia de plantillas.

    Carga de Plantillas.
    Django proporciona un API cómodo y eficaz para la carga de plantillas del sistema de archivos, con el objetivo de eliminar la redundancia, tanto en las llamadas de carga de plantillas como en las plantillas en sí mismas.
    Para usar esta API de carga de plantillas, primero tendrá que decirle al marco donde se almacenan las plantillas. El lugar para hacerlo es su archivo de configuración settings.py que hemos mencionado en el capítulo anterior, cuando se introdujo la propiedad ROOT_URLCONF.
    Abra settings.py y encuentre la propiedad TEMPLATE_DIRS. De forma predeterminada, es una tupla vacía, y es probable que contenga algunos comentarios autogenerados:
    TEMPLATE_DIRS = (
    # Put strings here, like “/home/html/django_templates”
    # or “C:/www/django/templates”.
    # Always use forward slashes, even on Windows.
    # Don’t forget to use absolute paths, not relative paths.
    )
    Este ajuste le indica al mecanismo de carga de plantillas de Django donde buscar las plantillas. Elija un directorio donde desea almacenar sus plantillas y añadalo a TEMPLATE_DIRS, así:
    TEMPLATE_DIRS = (
    ‘/home/django/mysite/templates’,
    )
    Hay algunas cosas que debe recordar:
    • Usted puede especificar cualquier directorio que desee, siempre y cuando el directorio y las plantillas dentro de ese directorio sean legibles por la cuenta de usuario en las que el servidor Web se ejecuta. Se recomienda la creación de un directorio de plantillas dentro de su proyecto (es decir, dentro del directorio que ha creado mysite)
    • Si su TEMPLATE_DIRS sólo contiene un directorio, no se olvide de la coma al final de la cadena del directorio. Python requiere comas dentro de tuplas de un solo elemento para eliminar la ambigüedad de la tupla de una expresión en paréntesis.
    • Si está en Windows, incluya la letra de la unidad y utilice las barra inclinadas al estilo Unix en lugar de las barras invertidas.
    Lo más simple es utilizar rutas absolutas (es decir, rutas de directorios que comienzan en la raíz del sistema de archivos). Si quiere ser un poco más flexible, sin embargo, usted puede construir TEMPLATE_DIRS dinámicamente, como en este ejemplo:
    import os.path
    TEMPLATE_DIRS = (
    os.path.join(os.path.dirname(__file__), ‘templates’).replace(‘\’,'/’),
    )
    Este ejemplo utiliza la variable “mágica” de Python __file__, que se ajusta automáticamente al nombre de archivo del módulo de Python en que reside el código. Se pone el nombre del directorio que contiene a settings.py (os.path.dirname), y se une con las plantillas de una manera (os.path.join), y entonces asegura que todo lo que se utiliza sean barras inclinadas en lugar de barras invertidas (en el caso de Windows).
    Con TEMPLATE_DIRS activo, el siguiente paso es cambiar el código para el uso de la funcionalidad de la carga de plantillas de Django en lugar de codificar a pelo las rutas de las plantillas. Volviendo a nuestra vista current_datetime, vamos a cambiarla de esta manera:
    from django.template.loader import get_template
    from django.template import Context
    from django.http import HttpResponse
    import datetime
    def current_datetime(request):
    now = datetime.datetime.now()
    t = get_template(‘current_datetime.html’)
    html = t.render(Context({‘current_date’: now}))
    return HttpResponse(html)
    La función get_template() toma un nombre de plantilla como argumento, busca dónde la plantilla residee en el sistema de archivos, abre ese archivo, y devuelve un objeto Template compilado.
    Si get_template() no puede encontrar la plantilla con el nombre que se le da, lanza una excepción TemplateDoesNotExist.
    Ahora, crear el archivo current_datetime.html dentro de su directorio de plantillas mediante el siguiente código de plantilla:
    It is now {{ current_date }}.
    Actualice la página en el explorador Web, y usted debería ver la página completamente renderizada.
     render_to_response()
    Hemos mostrado cómo cargar una plantilla, rellenar un contexto, y devolver un objeto HttpResponse con el resultado de la plantilla renderizada. Lo hemos optimizado mediante el uso de get_template() en lugar de la codificación a pelo de las plantillas y las rutas de plantillas. Sin embargo, todavía se requiere una buena cantidad de código para escribir todas esas cosas. Debido a que estos pasos son iguales, Django proporciona una abreviatura que le permite cargar una plantilla, renderizarla, y devolver un HttpResponse, todo en una sola línea de código.

    Esta abreviatura es una función llamada render_to_response(), que reside en el módulo django.shortcuts.
    Aquí está el ejemplo current_datetime reescrito para utilizar render_to_response():
    from django.shortcuts import render_to_response
    import datetime
    def current_datetime(request):
    now = datetime.datetime.now()
    return render_to_response(‘current_datetime.html’, {‘current_date’: now})
    El primer argumento de render_to_response() es el nombre de la plantilla a usar. El segundo argumento, si lo hay, debe ser un diccionario para usar en la creación de un contexto para la plantilla. Si usted no proporciona un segundo argumento, render_to_response() utiliza un diccionario vacío.
     locals()

    Muchas veces, usted se encontrará que usted mismo cálcula algunos valores, los almacena en variables (por ejemplo, now en el código anterior), y envía esas variables a la plantilla. Esto es un poco redundante y también significa escribir más.
    Usted puede usar la función Python llamada locals(). Esta devuelve un diccionario que asigna todos los nombres de variables locales a sus valores, donde local significa todas las variables que han sido definidas en el ámbito local. Así, la vista anterior podría reescribirse así:
    def current_datetime(request):
    current_date = datetime.datetime.now()
    return render_to_response(‘current_datetime.html’, locals())
    Hemos cambiado el nombre de la variable a current_date ahora, ya que ese es el nombre de variable que la plantilla espera.

    Subdirectorios en get_template()
    Puede ser difícil de manejar el almacenar todas sus plantillas en un solo directorio. Usted podría almacenar plantillas en subdirectorios de su directorio de plantillas, y eso está bien. De hecho, le recomendamos hacerlo; algunas características más avanzadas de Django (como el sistema de vistas genéricas) esperan esta disposición de plantillas por defecto.
    t = get_template(‘dateapp/current_datetime.html’)
    Ya que render_to_response() es una pequeña envoltura alrededor de get_template(), usted puede hacer lo mismo con el primer argumento de render_to_response(), así:
    return render_to_response(‘dateapp/current_datetime.html’, {‘current_date’: now})

    La etiqueta de plantilla include.
    Podemos introducir una etiqueta de plantilla integrada: {% include%}. Esta etiqueta permite incluir el contenido de otra plantilla. El argumento de la etiqueta debe ser el nombre de la plantilla a incluir, y el nombre de la plantilla puede ser una variable o una cadena entre comillas simples o dobles. Cada vez que tenga el mismo código en varias plantillas, considere el uso de {% include %} para eliminar la redundancia.
    Estos dos ejemplos incluyen el contenido de la plantilla nav.html. Los ejemplos son equivalentes e ilustran bien el uso de las comillas simples o dobles:
    {% include ‘nav.html’ %}
    {% include “nav.html” %}
    El siguiente ejemplo incluye el contenido de la plantilla, cuyo nombre figura en la variable template_name:
    {% include template_name %}
    Al igual que en get_template(), el nombre del fichero de la plantilla se determina mediante la adición al directorio de plantillas de TEMPLATE_DIRS para el nombre de la plantilla.
    La plantillas incluidas son evaluadas dentro del contexto de la plantilla que las incluye. Por ejemplo, considere estas dos plantillas:
    # mypage.html
    {% include “includes/nav.html” %}
    <h1>{{ title }}</h1>
    # includes/nav.html
    <div id=”nav”>You are in: {{ current_section }}</div>
    Si renderiza mypage.html con un contexto que contiene current_section, entonces la variable estará disponible en la plantilla incluida, como era de esperar.
    Si, en una etiqueta {% include %}, no se encuentra una plantilla con el nombre dado, Django hará una de estas 2 cosas:
    • Si DEBUG es True, verá una excepción TemplateDoesNotExist en una página de error de Django.
    • Si DEBUG es False, la etiqueta fallará de forma silenciosa, no visualizando nada en el lugar de la etiqueta.
      Nuestros ejemplos de plantillas hasta ahora han sido pequeños fragmentos de código HTML, pero en el mundo real usted utilizará el sistema de plantillas de Django para crear páginas enteras de HTML. Esto lleva a un problema de desarrollo web común: a través de un sitio Web, ¿cómo se puede reducir la duplicación y la redundancia de áreas de página comunes, tales como la navegación de todo el sitio?
      Una forma clásica de resolver este problema es usar includes de lado servidor, las directivas que usted puede incrustar dentro de sus páginas HTML para incluir una página web dentro de otra. De hecho, Django soporta esta aproximación con la etiqueta {% include %} que acabamos de describir. Pero la forma preferida de resolver este problema con Django es utilizar una estrategia más elegante llamado herencia de plantillas.
      django-templates-0-317x450
      En esencia, la herencia de plantillas le permite construir una plantilla “esqueleto” base que contiene todas las partes comunes de su sitio y define “bloques” que las plantillas hijas puede rellenar.

      Veamos un ejemplo de esto creando una plantilla más completa para nuestra vista current_datetime, editando el archivo current_datetime.html:
      <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN”>
      <html lang=”en”>
      <head>
      <title>The current time</title>
      </head>
      <body>
      <h1>My helpful timestamp site</h1>
      It is now {{ current_date }}.
      <hr>Thanks for visiting my site.
      </body>
      </html>
      Eso se ve muy bien, pero ¿qué sucede cuando queremos crear una plantilla para otra vista – por ejemplo, la vista hours_ahead? Si queremos volver a hacer otra plantilla HTML agradable, válida, completa, nos quedará algo como esto:
      <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN”>
      <html lang=”en”>
      <head>
      <title>Future time</title>
      </head>
      <body>
      <h1>My helpful timestamp site</h1>
      In {{ hour_offset }} hour(s), it will be {{ next_time }}.
      <hr>Thanks for visiting my site.
      </body>
      </html>
      Es evidente que hay mucho HTML duplicado. Imagínese si tuviéramos un sitio más típico, incluyendo una barra de navegación, una hojas de estilo, tal vez algo de JavaScript – empezaremos metiendo todo ese HTML redundante en cada plantilla.
      La solución de include de lado servidor a este problema es factorizar las partes comunes de ambas plantillas y guardarlos en distintos fragmentos de plantilla, que luego son incluidos en cada plantilla. Tal vez desee guardar la parte superior de la plantilla en un archivo llamado header.html:
      <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN”>
      <html lang=”en”>
      <head>
      y quizá almacenar la parte inferior en un fichero llamado footer.html:
      <hr>
      <p>Thanks for visiting my site.</p>
      </body>
      </html>
      Con una estrategia basada en include, los encabezados y los pies de página son fáciles. Es el punto medio el desordenado. En este ejemplo, ambas páginas tienen un título -<h1>My helpful timestamp site </h1> pero ese título no puede encajar en header.html porque el <title> en ambas páginas es diferente. Si incluimos el <h1> en la cabecera, tendríamos que incluir el <title>, que no nos permitiría personalizarlo por página.

      El sistema de herencia de plantillas de Django soluciona estos problemas. Puede pensar en ello como una versión dentro-fuera de los includes de lado servidor. En lugar de definir los fragmentos de código que son comunes, se definen los fragmentos de código que son diferentes.

      El primer paso es definir una plantilla base, un esqueleto de la página que las plantillas hijas rellenarán después. Aquí hay una plantilla base para nuestro ejemplo en curso:
      <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN”>
      <html lang=”en”>
      <head>
      <title>{% block title %}{% endblock %}</title>
      </head>
      <body>
      <h1>My helpful timestamp site</h1>
      {% block content %}{% endblock %}
      {% block footer %}
      <hr>
      <p>Thanks for visiting my site.</p>
      {% endblock %}
      </body>
      </html>
      Esta plantilla, que llamaremos base.html, define un documento de esqueleto HTML sencillo que se utilizará para todas las páginas del sitio. Es el trabajo de las plantillas hijas reemplazar, añadir o dejar vacío el contenido de los bloques.

      Estamos utilizando una etiqueta de plantilla que no hemos visto antes: la etiqueta {% block %}. Todo lo que hace una etiqueta {% block %} es decirle al motor de plantillas que una plantilla hija puede sustituir aquellas partes de la plantilla.
      Ahora que tenemos esta plantilla base, podemos modificar nuestra plantilla current_datetime.html existente:
      {% extends “base.html” %}
      {% block title %}The current time{% endblock %}
      {% block content %}
      <p>It is now {{ current_date }}.</p>
      {% endblock %}
      Vamos a crear una plantilla para la vista hours_ahead del Capítulo 3. Se podría parecer a esto:
      {% extends “base.html” %}
      {% block title %}Future time{% endblock %}
      {% block content %}
      <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
      {% endblock %}
      ¿No es esto bonito? Cada plantilla contiene sólo el código que es único para esa plantilla. No hay redundancia. Si usted necesita hacer un cambio de diseño de todo el sitio, sólo haga el cambio a base.html, y todas las otras plantillas inmediatamente reflejarán el cambio.

      He aquí cómo funciona. Cuando se carga la plantilla current_datetime.html, el motor de plantillas ve la etiqueta {% extends %}, notando que esa plantilla es una plantilla hija. El motor carga inmediatamente la plantilla padre – en este caso, base.html.
      En ese momento, el motor de plantillas nota las tres etiquetas {% block %} de base.html y sustituye esos bloques con el contenido de la plantilla hija.
      La herencia no afecta al contexto de la plantilla. En otras palabras, cualquier plantilla en el árbol de herencia tendrá acceso a cada una de sus variables de plantilla en el contexto.

      Puede utilizar tantos niveles de herencia, según sea necesario. Una forma común de utilizar la herencia es el siguiente enfoque de tres niveles:
      Crear una plantilla base.html que contenga el diseño principal de su sitio. Esta contiene las cosas que rara vez o nunca se cambian.
      1. Crear una plantilla base_SECTION.html por cada sección del sitio (por ejemplo, base_photos.html y base_forum.html). Estas plantillas extienden a base.html e incluyen estilos y diseño específicos de la sección.
      2. Crear plantillas individuales para cada tipo de página, como una página del foro o una galería de fotos. Estas plantillas extienden a la plantilla de la sección correspondiente.
      Este método maximiza la reutilización de código y facilita el añadir elementos a las zonas comunes, como la sección de navegación.
      Aquí hay algunas pautas para trabajar con herencia de plantillas:
      • Si usted usa {% extends %} en una plantilla, debe ser la primera etiqueta de esa plantilla.
      • Generalmente, cuanto más etiquetas {% block %} en sus plantillas base, mejor. Recordar que las plantillas hijas no tienen que definir todos los bloques de los padres, así que usted puede definir en las plantillas hijas sólo los que necesita.
      • Si usted encuentra duplicación de código en varias plantillas, probablemente significa que usted debe mover el código a una etiqueta {% block %} de una plantilla padre.
      • Si usted necesita obtener el contenido del bloque de la plantilla padre, use {{ block.super }}, que es una variable “mágica” que proporciona el texto renderizado de la plantilla padre. Esto es útil si desea añadir el contenido de un bloque padre en lugar de sobreescribirlo completamente.
      • Usted no puede definir múltiples etiquetas {% block %} con el mismo nombre en la misma plantilla.
        Esta limitación existe porque una etiqueta de bloque funciona en ambas direcciones. Es decir, un etiqueta de bloque no sólo proporcionan un contenedor para rellenar, sino que también define el contenido que rellena el contenedor en el padre. Si hubiese dos etiquetas {% block %} llamadas iguales en una plantilla, el padre no sabría cual de los contenidos de bloque utilizar.
      • El nombre de plantilla que se pasa a {% extends %} se carga utilizando el mismo método que usa get_template(). Es decir, el nombre de la plantilla se añade a la propiedad TEMPLATE_DIRS.
      • En la mayoría de los casos, el argumento de {% extends %} será una cadena, pero puede ser una variable, si usted no sabe el nombre de la plantilla padre hasta tiempo de ejecución. Esto le permite hacer algunas cosas de forma dinámica.
      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:
      0