Curso Python. Volumen XIX: Framework Django. Parte IV

Escrito por Javier Ceballos Fernández

Bienvenidos un día más al curso de Python, hoy vamos a continuar utilizando el framework Django de Python. Vamos a continuar presentándoos la API que Django nos provee y os vamos a mostrar cómo se utiliza. Así que pongámonos manos a la obra.

Manejando la API de Django para Python

Lo primero que vamos hacer es invocar el “shell” de Python desde “Django”. Para esto tendremos que ejecutar el siguiente comando:

$ python manage.py shell

Utilizamos este comando en vez de abrir directamente la consola de Python porque dentro de “manage.py” tenemos configurada la variable de entorno “DJANGO_SETTINGS_MODULE”, que le proporciona a Django el “import path” al archivo “mysite/settings.py”.

Aunque si por el contrario no queréis usar “manage.py”, no habría problema. Bastaría con configurar la variable de entorno “DJANGO_SETTINGS_MODULE” a “mysite.settings”, ejecutar un “Shell” de Python, y configurar “Django”:

import django
django.setup()

Si al ejecutar estas líneas se lanza una excepción “AttributeError”, probablemente lo que esté ocurriendo es que la versión de “Django” que no coincide con la que estamos utilizando en el curso. Si es este el caso os aconsejamos que utilicéis la misma versión que estamos utilizando en el curso. No os olvidéis que tenéis que ejecutar Python en el mismo directorio que se encuentra “manage.py”, o también podéis configurar el “Python path” este directorio para que el “import.mysite” os funcione. Podéis encontrar más información aquí.

Ahora que ya tenemos arrancada una “Shell” vamos a explorar la API de base de datos:

from polls.models import Pregunta, Opcion
# Import the model classes we just wrote.
# No hay preguntas en el sistema todavia.

>>>Pregunta.objects.all()
[]

# Creamos una nueva pregunta.
# Esta activado el soporte para time zones por defecto. Por lo que
# Django espera a datetime con tzinfo para fecha_publi. Usar timezone.now()

>>>from django.utils import timezone
>>>q = Pregunta(texto_pregunta ="¿Qué hay de nuevo viejo?", fecha_publi =timezone.now())

# Guardar el objeto.
>>> q.save()

# Vamos a recuperar el ID de la pregunta guardada
>>> q.id
1

# Acceder a los campos del modelo utilizando Python.
>>> q.texto_pregunta
"¿Qué hay de nuevo viejo?"
>>> q.fecha_publi
>>>datetime.datetime(2017, 5, 23, 18, 0, 0, 325257, tzinfo=<UTC>)

# Cambiando los valores.
>>> q.texto_pregunta = "¿Qué pasa?"
>>> q.save()

# objects.all() nos muestra todas las preguntas guardadas.
>>> Pregunta.objects.all()

[<Pregunta: Pregunta object>]

Vemos que nos muestra “< Pregunta: Pregunta object>” y esto no es una representación muy útil del objeto “Pregunta”. Esto lo podemos corregir reeditando los modelos (recordamos que es el archivo “polls/models.py”) y agregando el método “__str__()” a “Pregunta” y “Opcion”:

polls/models.py
from django.db import models

class Pregunta(models.Model):

# ...

def __str__(self):

return self.texto_pregunta

class Opcion(models.Model):

# ...

def __str__(self):
    return self.texto_opcion

Es importante que agreguemos el método “__str__()” a nuestros modelos, ya que es la representación que utiliza “Django” en la interfaz de administración autogenerada. Si utilizáis la versión Python 2, deberíais definir el método “__unicode__()” que devuelva valores unicode. Los modelos de Django tienen una implementación por defecto de “__str__()” que llama a “__unicode__()” y convierte el resultado a un “bytestring UTF-8”. Esto quiere decir que unicode(p) devuelve un string Unicode, y str(p) devuelve un bytestring, codificado en UTF-8. Python hace lo contrario: object tiene un método __unicode__ que llama a __str__ e interpreta el resultado como un bytestring ASCII. Esta diferencia puede generar confusión.

Hasta ahora hemos usado métodos comunes de Python. Así que vamos a añadir uno más. El método que vamos a añadir utiliza la librería “datetime” de Python y la librería “timezone” de Django. La primera librería es una de las librerías estándar de Python que nos ayuda a manejar fechas y la segunda nos ofrece las utilidades de “Django” para manejar las zonas horarias:

polls/models.py
import datetime

from django.db import models
from django.utils import timezone

class Pregunta(models.Model):

# ...

def seHaPublicadoAhora(self):
    return self.fecha_publi >= timezone.now() - datetime.timedelta(days=1)

Guardamos estos cambios y abrimos una nueva sesión en el “Shell” ejecutando “python manage.py shell” nuevamente e ir ejecutando las siguientes líneas:

>>>from polls.models import Pregunta, Opcion
>>>Pregunta.objects.all()

[<Pregunta: ¿Qué pasa?>]

# Vamos a utilizar filtros de busqueda
>>> Pregunta.objects.filter(id=1)

[<Pregunta: ¿Qué pasa?>]

>>> Pregunta.objects.filter(texto_pregunta__startswith='¿Qué')

[<Pregunta: ¿Qué pasa?>]

# Recuperar las preguntas del ultimo año.
>>> from django.utils import timezone
>>> ano_actual= timezone.now().year
>>> Pregunta.objects.get(fecha_publi__year= ano_actual)
<Pregunta: ¿Qué pasa?>

# Preguntamos por un id que no existe para que de un error.

>>> Question.objects.get(id=2)

Traceback (most recent call last):

...

DoesNotExist: Pregunta matching query does not exist.

# Buscar por primary key. Es muy normal en Django
# Es igual que Pregunta.objects.get(id=1).

>>> Pregunta.objects.get(pk=1)

<Pregunta: ¿Qué pasa?>

# Ejecutar nuestro nuevo método.

>>> q = Pregunta.objects.get(pk=1)
>>> q.seHaPublicadoAhora()

True

# Vamos a añadir a la pregunta opciones.
>>> q = Pregunta.objects.get(pk=1)

# Mostramos todos las opciones

>>> q.opcion_set.all()
[]

# Creamos 3 opciones.
>>> q.opcion_set.create(texto_opcion='No mucho', votos=0)
<Opcion: No mucho>

>>> q.opcion_set.create(texto_opcion ='El mar', votes=0)

<Opcion: El mar>

>>> c = q.opcion_set.create(texto_opcion ='Nada nuevo', votes=0)

# El objeto Opcion tiene acceso a sus objetos Pregunta relacionados

>>> c.pregunta

<Pregunta: ¿Qué pasa?>

# Al reves tambien.

>>> q.opcion_set.all()

[<Opcion: No mucho>, <Opcion: El mar>, <Opcion: Nada nuevo>]

>>> q.opcion_set.count()

# La API reconoce la relacion existente entre objetos de manera automatica
# Usaremos dos guiones bajos para serparar las relaciones.
# Encontrar todas las opciones de cualquier pregunta que se haya publicado este ano
# (reutilizar la variable 'current_year' que creamos anteriormente).

>>> Opcion.objects.filter(pregunta__fecha_publi__year=current_year)

[<Opcion: No mucho>,<Opcion: El mar>,<Opcion: Nada nuevo>]

# Vamos a borrar una opcion.

>>> c = q.opcion_set.filter(texto_opcion__startswith='Nada')
>>> c.delete()

Si queréis más información sobre las relaciones entre los modelos, os aconsejamos que os dirijáis a la documentación de “Django”. Si queréis más información sobre cómo se utilizan los dos guiones vamos para realizar búsquedas utilizando la API, acceder aquí. Por último si queréis ver la API completa de base de datos de “Django” acceder aquí.

Esto es todo por hoy, hemos dado otro pequeño paso para seguir estudiando y entendiendo este framework. Os invitamos como siempre a que sigáis probando y en este caso a ir leyendo los enlaces que os vamos dejando. Y para todos los que se acaban de incorporar indicarles que tenemos un índice con todos los capítulos del curso, ya que nunca es tarde para empezar.

Últimos análisis

Valoración RZ
7
Valoración RZ
9
Valoración RZ
8
Valoración RZ
8
Valoración RZ
8
Valoración RZ
8
Valoración RZ
10