Taula de continguts

Tractament d'imatges en Django

Les imatges, en Django, necessiten un tractament particular.

, , , , , ,


Algunes consideracions

Django processa eficientment les dades de l'aplicació, però no és ràpid per servir els arxius voluminosos com les imatges, o d'altres que es demanen molt sovint com els arxius estàtics (CSS, etc.).

Per això el tractament d'imatges té certes peculiaritats. Guardarem els binaris en una carpeta, típicament media/ i en producció deixarem que les serveixi el servidor web (Apache o Nginx). Django ho pot fer, però no és convenient.

Així, un esquena de posada en producció de Django seria quelcom similar a:

Per saber més podeu llegir sobre Django en produccio en aquesta wiki.


Configuració imatges i carpeta 'media'

Instal·lar la biblioteca Pillow per al tractament d'imatges:

(env) $ pip install Pillow

Afegir el camp desijat als models

models,py
from django.db import models
 
class Producte(models.Model):
    nom = models.CharField(max_length=100)
    imatge = models.ImageField(upload_to='productes/')

Configurar la carpeta de càrregues d'arxius (típicament media/) al settings.py:

settings.py
import os
 
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

Afegir la configuració a urls.py per servir els arxius media i estàtics quan estiguem en desenvolupament:

urls.py
from django.conf import settings
from django.conf.urls.static import static
 
urlpatterns = [
    # ... les teves URLs existents ...
]
 
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


Visualitzacions a l'admin panel

Personalitzar la vista a l'admin panel per veure les imatges:

admin.py
from django.contrib import admin
from django.utils.html import format_html
from .models import Producte
 
class ProducteAdmin(admin.ModelAdmin):
    # Afegeix el mètode a readonly_fields perquè es mostri en la pàgina d'edició
    readonly_fields = ('vista_previa_imatge',)
 
    # Defineix quins camps es mostren en el formulari d'edició
    fields = ('nom', 'imatge', 'vista_previa_imatge')
 
    def vista_previa_imatge(self, obj):
        if obj.imatge:
            # Retorna l'etiqueta HTML amb l'URL de la imatge
            return format_html('<img src="{}" width="200" height="150" style="object-fit: cover;" />', obj.imatge.url)
        return "No hi ha imatge"
 
    vista_previa_imatge.short_description = 'Previsualització'
 
admin.site.register(Producte, ProducteAdmin)

I també podríem personalitzar la vista de llista de l'admin panel:

admin.py
class ProducteAdmin(admin.ModelAdmin):
    list_display = ('nom', 'vista_previa_imatge')
 
    def vista_previa_imatge(self, obj):
        if obj.imatge:
            return format_html('<img src="{}" width="50" height="50" style="object-fit: cover;" />', obj.imatge.url)
        return "Sense imatge"
 
    vista_previa_imatge.short_description = 'Miniatura'