# Django 6.0.5 documentation

# Hantera filer

Detta dokument beskriver Djangos API:er för filåtkomst för filer som till exempel de som laddas upp av en användare. API:erna på lägre nivå är tillräckligt generella för att du ska kunna använda dem för andra ändamål. Om du vill hantera ”statiska filer” (JS, CSS, etc.), se Hur man hanterar statiska filer (t.ex. bilder, JavaScript, CSS).

Som standard lagrar Django filer lokalt med hjälp av inställningarna `MEDIA_ROOT` och `MEDIA_URL`. Exemplen nedan förutsätter att du använder dessa standardinställningar.

Django tillhandahåller dock sätt att skriva anpassade ”fillagringssystem” som gör att du helt kan anpassa var och hur Django lagrar filer. I andra halvan av detta dokument beskrivs hur dessa lagringssystem fungerar.

## Använda filer i modeller

När du använder en `FileField` eller `ImageField` tillhandahåller Django en uppsättning API:er som du kan använda för att hantera den filen.

Tänk på följande modell, som använder en `ImageField` för att lagra ett foto:

    from django.db import models

    class Car(models.Model):
        name = models.CharField(max_length=255)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        photo = models.ImageField(upload_to="cars")
        specs = models.FileField(upload_to="specs")

Varje `Car`-instans har ett `photo`-attribut som du kan använda för att få fram detaljerna i det bifogade fotot:

    >>> car = Car.objects.get(name="57 Chevy")
    >>> car.photo
    <ImageFieldFile: cars/chevy.jpg>
    >>> car.photo.name
    'cars/chevy.jpg'
    >>> car.photo.path
    '/media/cars/chevy.jpg'
    >>> car.photo.url
    'https://media.example.com/cars/chevy.jpg'

Detta objekt - `car.photo` i exemplet - är ett `File`-objekt, vilket innebär att det har alla de metoder och attribut som beskrivs nedan.

Observera

Filen sparas som en del av att modellen sparas i databasen, så det faktiska filnamnet som används på disken kan man inte lita på förrän efter att modellen har sparats.

Du kan till exempel ändra filnamnet genom att ställa in filens `name` till en sökväg i förhållande till fillagringsplatsen (`MEDIA_ROOT` om du använder standard `FileSystemStorage`):

    >>> import os
    >>> from django.conf import settings
    >>> initial_path = car.photo.path
    >>> car.photo.name = "cars/chevy_ii.jpg"
    >>> new_path = os.path.join(settings.MEDIA_ROOT, car.photo.name)
    >>> # Move the file on the filesystem
    >>> os.rename(initial_path, new_path)
    >>> car.save()
    >>> car.photo.path
    '/media/cars/chevy_ii.jpg'
    >>> car.photo.path == new_path
    True

Så här sparar du en befintlig fil på disken till en `FileField`:

    >>> from pathlib import Path
    >>> from django.core.files import File
    >>> path = Path("/some/external/specs.pdf")
    >>> car = Car.objects.get(name="57 Chevy")
    >>> with path.open(mode="rb") as f:
    ...     car.specs = File(f, name=path.name)
    ...     car.save()
    ...

Observera

Medan `ImageField` icke-bilddataattribut, såsom `höjd`, `bredd` och `storlek` är tillgängliga på instansen, kan de underliggande bilddata inte användas utan att öppna bilden igen. Exempel på detta:

    >>> from PIL import Image
    >>> car = Car.objects.get(name="57 Chevy")
    >>> car.photo.width
    191
    >>> car.photo.height
    287
    >>> image = Image.open(car.photo)
    # Raises ValueError: seek of closed file.
    >>> car.photo.open()
    <ImageFieldFile: cars/chevy.jpg>
    >>> image = Image.open(car.photo)
    >>> image
    <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=191x287 at 0x7F99A94E9048>

## Objektet ”Fil

Internt använder Django en `django.core.files.File`-instans varje gång den behöver representera en fil.

För det mesta använder du en `Fil` som Django har gett dig (dvs. en fil som är kopplad till en modell enligt ovan, eller kanske en uppladdad fil).

Om du behöver konstruera en `File` själv är det enklaste sättet att skapa en med hjälp av ett Python-inbyggt `file`-objekt:

    >>> from django.core.files import File

    # Create a Python file object using open()
    >>> f = open("/path/to/hello.world", "w")
    >>> myfile = File(f)

Nu kan du använda alla dokumenterade attribut och metoder i `File`-klassen.

Tänk på att filer som skapas på detta sätt inte stängs automatiskt. Följande metod kan användas för att stänga filer automatiskt:

    >>> from django.core.files import File

    # Create a Python file object using open() and the with statement
    >>> with open("/path/to/hello.world", "w") as f:
    ...     myfile = File(f)
    ...     myfile.write("Hello World")
    ...
    >>> myfile.closed
    True
    >>> f.closed
    True

Att stänga filer är särskilt viktigt när man använder filfält i en loop över ett stort antal objekt. Om filer inte stängs manuellt efter åtkomst kan det uppstå risk för att filbeskrivare tar slut. Detta kan leda till följande fel:

    OSError: [Errno 24] Too many open files

## Lagring av filer

Bakom kulisserna delegerar Django beslut om hur och var filer ska lagras till ett fillagringssystem. Detta är det objekt som faktiskt förstår saker som filsystem, öppning och läsning av filer etc.

Djangos standard fillagring är `'``django.core.files.storage.FileSystemStorage``'`. Om du inte uttryckligen anger ett lagringssystem i `default`-nyckeln i inställningen `STORAGES`, är det detta som kommer att användas.

Se nedan för mer information om det inbyggda standard fillagringssystemet, och se Så här skriver du en anpassad lagringsklass för information om hur du skriver ditt eget fillagringssystem.

### Förvaringsobjekt

Även om du för det mesta vill använda ett `File`-objekt (som delegerar till rätt lagring för filen) kan du använda fillagringssystem direkt. Du kan skapa en instans av någon anpassad fillagringsklass, eller - ofta mer användbart - du kan använda det globala standardlagringssystemet:

    >>> from django.core.files.base import ContentFile
    >>> from django.core.files.storage import default_storage

    >>> path = default_storage.save("path/to/file", ContentFile(b"new content"))
    >>> path
    'path/to/file'

    >>> default_storage.size(path)
    11
    >>> default_storage.open(path).read()
    b'new content'

    >>> default_storage.delete(path)
    >>> default_storage.exists(path)
    False

Se API för fillagring för API:et för fillagring.

### Den inbyggda lagringsklassen för filsystem

Django levereras med en `django.core.files.storage.FileSystemStorage`-klass som implementerar grundläggande lokal filsystemlagring.

Till exempel kommer följande kod att lagra uppladdade filer under `/media/photos` oavsett vad din `MEDIA_ROOT`-inställning är:

    from django.core.files.storage import FileSystemStorage
    from django.db import models

    fs = FileSystemStorage(location="/media/photos")

    class Car(models.Model):
        ...
        photo = models.ImageField(storage=fs)

Custom storage systems fungerar på samma sätt: du kan skicka in dem som argumentet `storage` till en `FileField`.

### Använda en callable

Du kan använda en callable som `storage` parameter för `FileField` eller `ImageField`. Detta gör att du kan ändra den använda lagringen vid körning, till exempel välja olika lagring för olika miljöer.

Din callable kommer att utvärderas när dina modellklasser laddas, och måste returnera en instans av `Storage`.

Till exempel:

    from django.conf import settings
    from django.db import models
    from .storages import MyLocalStorage, MyRemoteStorage

    def select_storage():
        return MyLocalStorage() if settings.DEBUG else MyRemoteStorage()

    class MyModel(models.Model):
        my_file = models.FileField(storage=select_storage)

För att ställa in en lagring som definieras i inställningen `STORAGES` kan du använda `storages`:

    from django.core.files.storage import storages

    def select_storage():
        return storages["mystorage"]

    class MyModel(models.Model):
        upload = models.FileField(storage=select_storage)

Eftersom den anropsbara utvärderas när dina modellklasser laddas, om du behöver åsidosätta inställningen `STORAGES` i tester, bör du använda en `LazyObject`-underklass istället:

    from django.core.files.storage import storages
    from django.utils.functional import LazyObject

    class OtherStorage(LazyObject):
        def _setup(self):
            self._wrapped = storages["mystorage"]

    my_storage = OtherStorage()

    class MyModel(models.Model):
        upload = models.FileField(storage=my_storage)

`LazyObject` fördröjer utvärderingen av lagringen tills den faktiskt behövs, vilket gör att `override_settings()` kan träda i kraft:

    @override_settings(
        STORAGES={
            "mystorage": {
                "BACKEND": "django.core.files.storage.InMemoryStorage",
            }
        }
    )
    def test_storage():
        model = MyModel()
        assert isinstance(model.upload.storage, InMemoryStorage)