En Wagtail como crear páginas mediante un script de Python | Programador Web Valencia

En Wagtail como crear páginas mediante un script de Python

3 minutos

Django

Wagtail es un CMS que se integra con Django y nos permite crear páginas de forma visual. No obstante, hay situaciones donde debemos crear páginas de forma automática como, por ejemplo, cuando tenemos que importar un gran número de páginas desde un JSON o es necesario dar herramientas a los diseñadores web con datos falsos lo más diversos posible.

Para ello, podemos crear un script de Python que se conecte con los modelos de Django y cree las páginas que necesitemos.

Contexto

Partiremos de 2 paginas clásicas de un blog común. BlogListPage será página que contiene las entradas de blog y BlogIndexPage que es la página individual de cada entrada, que a su vez es hija de BlogListPage.

class BlogListPage(Page):

	subpage_types = ["public.BlogPage"]


class BlogIndexPage(Page):
    summary = models.TextField(_("Summary"), default="")
    body = RichTextField()
    date = models.DateField(_("Post date"))
    cover = models.ForeignKey(
        "wagtailimages.Image",
        blank=False,
        on_delete=models.PROTECT,
        related_name="blog_cover",
    )
    is_highlighted = models.BooleanField(_("Is highlighted?"), default=False)

	content_panels = Page.content_panels + [
        FieldPanel("summary"),
        FieldPanel("body"),
        FieldPanel("date"),
        FieldPanel("is_highlighted"),
        FieldPanel("cover"),
    ]

	parent_page_types = ["public.BlogListPage"]
    subpage_types = []

Como puedes observar, en BlogIndexPage tenemos nuevos campos con tipos de lo más diversos.

  • summary es un campo de texto.
  • body es un campo de texto enriquecido (salida en HTML).
  • date es una fecha.
  • cover es una imagen.
  • is_highlighted es un booleano.

Cada uno de ellos lo trataremos de forma individual.

Solución

1. Subir imagen

Nota: Ignora este paso si no necesitas incluir una imagen.

El campo cover es una imagen, por ello previamente habrá que subirla o seleccionar una que ya exista en la base de datos.

Si es el segundo caso, reutilizar una existente, podemos buscarla con el modelo Image de Wagtail.

from wagtail.images.models import Image
my_new_cover = Image.objects.filter(title="Mi imagen").first()

En caso de necesitar subir una nueva imagen, se complica pero no es imposible.

En el siguiente ejemplo, subiremos una imagen aleatoria descargada directamente desde internet.

from wagtail.images.models import Image
import requests
from django.core.files import File
from tempfile import NamedTemporaryFile
from random import randint

url_random_imagen = (
	f"https://cdn.jsdelivr.net/gh/tanrax/place-image-random/images/{randint(1, 1000)}.jpg"
)
r = requests.get(url_random_imagen)
img_temp = NamedTemporaryFile(delete=True)
img_temp.write(r.content)
img_temp.flush()
my_new_image = File(img_temp)
my_new_cover = Image.objects.create(title="Mi nueva imagen", file=my_new_image)

En ambos casos, ya tenemos la imagen en la variable my_new_cover. Podemos pasar a crear la página.

2. Crear página

Primero debemos importar nuestros modelos. En este caso, BlogListPage y BlogIndexPage están en app.public.models. En tu situación puede que estén en otro sitio.

from app.public.models import BlogListPage, BlogIndexPage

Aprovecharemos para importar datetime con el objetivo de crear una fecha.

from datetime import datetime

Un requisito para crear una página de Wagtail es instanciar la página padre. En este caso, BlogListPage.

parent_page = BlogListPage.objects.first().specific

Se necesita el método specific para obtener la instancia de la página y no el modelo.

Ahora ya podemos crear la página. En este caso, BlogIndexPage.

new_item = BlogIndexPage()
new_item.title = "Mi titulo"
new_item.body = "<p>Mi contenido</p>"
new_item.date = datetime.now()
new_item.summary = "Soy un resumen"
new_item.cover = my_new_cover
new_item.is_highlighted = False

Por último, debemos añadir la página a la página padre y listo.

parent_page.add_child(instance=new_item)

La página ya está creada. Si necesitas crear más, puedes repetir el proceso todas las veces que necesites.

Extra: Crear páginas masivas con contenido falso o de prueba

Si necesitas crear un gran número de páginas, puedes utilizar la librería Faker.

from faker import Faker
fake = Faker()

Con ella, puedes crear contenido falso para rellenar los campos de las páginas.

En el siguiente ejemplo se crean 10 páginas con contenido falso.

from faker import Faker
from app.public.models import BlogListPage, BlogIndexPage
from datetime import datetime
from wagtail.images.models import Image
import requests
from django.core.files import File
from tempfile import NamedTemporaryFile
from random import randint

# Variables
fake = Faker()
parent_page = BlogListPage.objects.first().specific

# Functions

def get_random_image():
	url_random_imagen = (
		f"https://cdn.jsdelivr.net/gh/tanrax/place-image-random/images/{randint(1, 1000)}.jpg"
	)
	r = requests.get(url_random_imagen)
	img_temp = NamedTemporaryFile(delete=True)
	img_temp.write(r.content)
	img_temp.flush()
	return File(img_temp)

def create_image():
	my_new_image = get_random_image()
	return Image.objects.create(title=fake.sentence(), file=my_new_image)

def create_page():
	new_item = BlogIndexPage()
	new_item.title = fake.sentence()
	new_item.body = "\n".join([f"<p>{fake.sentence()}</p>" for _ in range(randint(10, 100))])
	new_item.date = fake.date_time_this_year()
	new_item.summary = fake.sentence()
	new_item.cover = create_image()
	new_item.is_highlighted = fake.boolean()
	parent_page.add_child(instance=new_item)

for i in range(10):
	create_page()

Si necesitas crear más, puedes cambiar el range(10) por el número de páginas que necesites.

Esta obra está bajo una Licencia Creative Commons Atribución-NoComercial-SinDerivadas 4.0 Internacional.

Atribución/Reconocimiento-NoComercial-SinDerivados 4.0 Internacional

¿Me ayudas?

Comprame un café
Pulsa sobre la imagen

No te sientas obligado a realizar una donación, pero cada aportación mantiene el sitio en activo logrando que continúe existiendo y sea accesible para otras personas. Además me motiva a crear nuevo contenido.

Comentarios

{{ comments.length }} comentarios

Nuevo comentario

Nueva replica  {{ formatEllipsisAuthor(replyComment.author) }}

Acepto la política de Protección de Datos.

Escribe el primer comentario

Tal vez también te interese...