GastroMóvil offloads all user-uploaded media to Cloudinary through theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/lffiesco-svg/gastromovil/llms.txt
Use this file to discover all available pages before exploring further.
django-cloudinary-storage package. This means uploaded images never touch the server’s local filesystem in production — they are streamed directly to Cloudinary and served from Cloudinary’s CDN. Static assets (CSS, JavaScript, Tailwind output) follow a different path and are served locally by WhiteNoise, keeping the two concerns cleanly separated.
Cloudinary Configuration
Cloudinary is initialised insettings.py using credentials loaded from environment variables:
DEFAULT_FILE_STORAGE to MediaCloudinaryStorage means every Django ImageField and FileField that calls .save() automatically uploads to Cloudinary without any per-field configuration.
The local media paths are kept as a fallback for development tooling:
In production
MEDIA_ROOT is never written to — all uploads go to Cloudinary.
The path is retained so that local management commands that reference
MEDIA_ROOT do not error out.Required Environment Variables
| Variable | Description |
|---|---|
CLOUDINARY_CLOUD_NAME | Your cloud name, visible in the Cloudinary console URL |
CLOUDINARY_API_KEY | API key from Settings → Access Keys |
CLOUDINARY_API_SECRET | API secret — treat it like a database password |
Image Fields and Validators
Two models inrestaurantes/models.py use CloudinaryField. Each has distinct upload requirements enforced by Django validators that run before the image is uploaded.
Restaurante.imagen — Strict PNG, 400 × 250 px
Restaurant banner images have two validators applied in sequence:
validar_png checks the filename extension. validar_dimensiones_restaurante opens the uploaded file with Pillow and verifies that both dimensions are exact — the image is rejected if it is even one pixel off.
Producto.imagen — Any format, no size restrictions
Product images have no format or dimension constraints:
blank=True, null=True, so a restaurant or product can be created without an image.
Uploading Images via the Restaurant Panel
Restaurant owners manage their images through the web-based restaurant panel. To update a restaurant banner:Log in as a restaurant owner
Navigate to
/usuarios/login and authenticate with a user account whose
rol is restaurante.Open the restaurant panel
After login you are redirected to
panel_restaurante. Click Editar
next to the restaurant whose banner you want to change.Upload the banner
In the edit form, select a PNG file that is exactly 400 × 250 px. The
form will reject the upload and display a validation error if either
requirement is not met.
Static Files (WhiteNoise)
Static assets are handled entirely separately from media uploads. WhiteNoise serves pre-collected static files directly from the Django process with aggressive caching headers — no CDN or object-storage bucket is needed for CSS and JS.CorsMiddleware) so that static files are served without hitting the Django view layer:
Building and Collecting Static Files
The Railway build command (fromrailway.toml) runs both steps automatically on every deploy:
tailwind build compiles the Tailwind CSS output into theme/static/ using the app defined by TAILWIND_APP_NAME = 'theme'. collectstatic --noinput then gathers all static files from STATICFILES_DIRS and every installed app into staticfiles_prod/.
For local development, run the two commands manually whenever you change CSS:
Tailwind’s JIT watcher (
python manage.py tailwind start) is also available
during development and will rebuild CSS on file changes automatically, so you
only need to run collectstatic once before the first local server start.