181 lines
7.9 KiB
Markdown
181 lines
7.9 KiB
Markdown
# 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](https://docs.astral.sh/uv/).
|
|
|
|
## Desarrollo
|
|
|
|
### Requisitos
|
|
|
|
- Python 3.13
|
|
- [uv](https://docs.astral.sh/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`.
|
|
- `gettext` si vas a regenerar/compilar traducciones
|
|
(`msgfmt`/`msguniq`/etc.) — en Debian/Ubuntu: `apt-get install gettext`.
|
|
|
|
### Puesta en marcha
|
|
|
|
```bash
|
|
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](#variables-de-entorno) más abajo). Para desarrollo
|
|
local basta con:
|
|
|
|
```env
|
|
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.
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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`):
|
|
|
|
```bash
|
|
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`:
|
|
|
|
```bash
|
|
uv run python manage.py build_pattern_detail_css
|
|
```
|
|
|
|
### Docker
|
|
|
|
```bash
|
|
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:
|
|
|
|
1. **`SECRET_KEY`**: un valor único y secreto (no el de desarrollo).
|
|
2. **`DEBUG=False`**.
|
|
3. **`ALLOWED_HOSTS`**: los dominios reales, no `*`.
|
|
4. **`CSRF_TRUSTED_ORIGINS`**: los orígenes reales (con esquema, p. ej.
|
|
`https://patrones.ejemplo.com`).
|
|
5. **`DATABASE_URL`**: apuntando a PostgreSQL.
|
|
6. **`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).
|
|
7. **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=True` y las credenciales de `S3_*` — 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`).
|