7.9 KiB
Crochet
Aplicación web para diseñar patrones de crochet con un editor visual, exportarlos a PDF y compartirlos con un enlace de solo lectura. Incluye cuentas de usuario para guardar y gestionar los propios patrones.
Funcionalidades
- Editor visual de patrones: secciones de título, subtítulo, texto, nota, materiales, imágenes y "patrón" (puntos con contador), todo reordenable por arrastre. El contenido se guarda bilingüe (es/en).
- Personalización de página: título, autor, imagen de portada, color de texto/acento/fondo, tipografía, tamaño de letra, alineación, tamaño y orientación de página.
- Exportación a PDF con WeasyPrint, usando el propio diálogo de impresión del navegador.
- Vista de solo lectura compartible (
pattern/<uuid>/), sin necesidad de cuenta ni de cargar el editor. - Cuentas de usuario: registro (con email, necesario para poder recuperar la contraseña), login/logout, ajustes de cuenta (cambiar email/contraseña, con HTMX) y recuperación de contraseña por email. Cada patrón pertenece a quien lo creó; solo su propietario puede editarlo o borrarlo.
- "Mis patrones": listado de los patrones propios con portada, fecha de actualización y accesos directos a editar/ver/eliminar.
- i18n completo (español/inglés): interfaz, URLs traducidas
(
/es/patron/...frente a/en/pattern/...) y contenido del propio patrón.
Stack técnico
- Backend: Django 6, servido en ASGI con Uvicorn.
- Base de datos: PostgreSQL en producción, SQLite por defecto en
desarrollo (configurable con
DATABASE_URL). - Frontend del editor: JavaScript vanilla (sin framework ni bundler), daisyUI + Tailwind CSS vía CDN con compilador JIT.
- Vista de solo lectura / PDF: Tailwind precompilado sin JS (WeasyPrint
no ejecuta JavaScript), generado con el CLI standalone de Tailwind (ver
python manage.py build_pattern_detail_css). - Imágenes: Pillow (variantes de la portada del patrón en varios
tamaños), almacenamiento en filesystem o S3 (
django-storages, opcional). - Estáticos: WhiteNoise con manifest comprimido.
- HTMX para los formularios de ajustes de cuenta.
- Gestión de dependencias: uv.
Desarrollo
Requisitos
- Python 3.13
- uv
- Librerías nativas de WeasyPrint (Pango, Cairo, GDK-Pixbuf) si vas a
generar/probar el PDF fuera de Docker — en Debian/Ubuntu:
apt-get install libpango-1.0-0 libpangocairo-1.0-0 fonts-dejavu-core. gettextsi vas a regenerar/compilar traducciones (msgfmt/msguniq/etc.) — en Debian/Ubuntu:apt-get install gettext.
Puesta en marcha
git clone <url-del-repositorio>
cd crochet
uv sync --group dev
Crea un archivo .env en la raíz del proyecto (ver
Variables de entorno más abajo). Para desarrollo
local basta con:
DEBUG=True
Con eso, la app arranca con SQLite, SECRET_KEY de desarrollo, envío de
email al backend de consola (se imprime en la terminal en vez de mandarse
de verdad) y sin credenciales adicionales.
uv run python manage.py migrate
uv run python manage.py createsuperuser # opcional, para /admin/
uv run python manage.py runserver
La app queda disponible en http://localhost:8000/.
Tests
uv run pytest
pytest-cov está incluido; para ver cobertura: uv run pytest --cov.
Traducciones
Las cadenas ya traducidas están compiladas y listas para usar. Si añades o
cambias texto traducible ({% trans %}/{% blocktrans %}, gettext_lazy):
uv run python manage.py makemessages -l es -l en
# revisa a mano cualquier entrada marcada como "#, fuzzy" antes de compilar
uv run python manage.py compilemessages
CSS precompilado de la vista de solo lectura / PDF
Solo hace falta volver a generarlo si cambian las clases de Tailwind
usadas en pattern_detail.html o pattern_render.py:
uv run python manage.py build_pattern_detail_css
Docker
docker build -t crochet .
docker run --rm -p 8000:8000 --env-file .env crochet
El Dockerfile instala las dependencias del sistema necesarias para
WeasyPrint y ejecuta scripts/build.sh (CSS precompilado, collectstatic,
compilemessages) al construir la imagen, y scripts/run.sh (Uvicorn) al
arrancar el contenedor.
Variables de entorno
Todas se leen en config/settings/env.py; sin .env, o si falta alguna,
se usan los valores por defecto indicados (pensados para desarrollo local).
| Variable | Por defecto | Descripción |
|---|---|---|
SECRET_KEY |
clave insegura de desarrollo | Cámbiala en producción. |
DEBUG |
False |
Activa páginas de error detalladas, Django Debug Toolbar y Silk. No debe estar activo en producción. |
ALLOWED_HOSTS |
* |
Lista separada por comas. Debe restringirse a los dominios reales en producción. |
CSRF_TRUSTED_ORIGINS |
http://localhost:8000 |
Lista separada por comas. Necesario si la app se sirve detrás de un dominio/HTTPS distinto. |
DATABASE_URL |
sqlite:///db.sqlite3 |
Formato django-environ (p. ej. postgres://usuario:password@host:5432/nombre_bd). |
S3_ENABLED |
False |
Si es True, los archivos subidos (imágenes de portada/patrón) se guardan en S3 en vez de en el filesystem local. |
S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY / S3_STORAGE_BUCKET_NAME / S3_ENDPOINT_URL |
vacío | Credenciales del bucket, solo necesarias si S3_ENABLED=True. |
EMAIL_BACKEND |
backend de consola | Usa django.core.mail.backends.smtp.EmailBackend para enviar emails de verdad (recuperación de contraseña). |
EMAIL_HOST / EMAIL_HOST_USER / EMAIL_HOST_PASSWORD / EMAIL_PORT |
vacío / vacío / vacío / 587 |
Credenciales SMTP, solo con el backend SMTP. |
DEFAULT_FROM_EMAIL |
webmaster@localhost |
Remitente de los emails salientes. La mayoría de proveedores SMTP rechazan enviar si no coincide con la cuenta autenticada (o un alias verificado). |
SUPPORT_EMAIL |
soporte@localhost |
Dirección de contacto que se muestra en el aviso que recibe el email anterior de una cuenta cuando alguien lo cambia (ver EmailUpdateForm). |
LOG_LEVEL |
INFO |
Nivel de log de Django y de la app (crochet). |
Existen además CORS_ORIGIN_WHITELIST, REDIS_HOST, REDIS_PORT,
CELERY_BROKER_URL, PAGE_SIZE e ITEMS_PER_PAGE en env.py: quedaron de
una plantilla de proyecto y actualmente no los usa ninguna parte de la
aplicación (no hay Celery, cachés en Redis, CORS ni paginación
configurados), así que no hace falta definirlos para desplegar.
Despliegue a producción
Como mínimo hay que ajustar, respecto al .env de desarrollo:
SECRET_KEY: un valor único y secreto (no el de desarrollo).DEBUG=False.ALLOWED_HOSTS: los dominios reales, no*.CSRF_TRUSTED_ORIGINS: los orígenes reales (con esquema, p. ej.https://patrones.ejemplo.com).DATABASE_URL: apuntando a PostgreSQL.EMAIL_BACKEND/EMAIL_HOST/EMAIL_HOST_USER/EMAIL_HOST_PASSWORD/DEFAULT_FROM_EMAIL: sin esto, el registro de usuarios funciona pero la recuperación de contraseña no llega a enviarse (se queda en el log en vez de salir por SMTP).- Almacenamiento de archivos: si vas a correr más de una instancia o
quieres que las imágenes sobrevivan a un redeploy del contenedor,
configura
S3_ENABLED=Truey las credenciales deS3_*— el filesystem local (por defecto) no es compartido ni persistente entre despliegues.
La imagen Docker ya ejecuta collectstatic, compilemessages y el
CSS precompilado al construirse, y sirve la app con Uvicorn (variables
WSGI_HOST/WSGI_WORKERS para ajustar host/nº de workers). WhiteNoise se
encarga de servir los estáticos directamente desde la propia app, sin
necesidad de un servidor/proxy de estáticos aparte.
Al hacer push a master se dispara la integración continua (tests) y,
si pasan, se construye y publica una imagen Docker (ver
.gitea/workflows/test-build.yaml).