# Django 6.0.5 documentation

# Serialisering av Django-objekt

Djangos serialiseringsramverk tillhandahåller en mekanism för att ”översätta” Django-modeller till andra format. Vanligtvis kommer dessa andra format att vara textbaserade och användas för att skicka Django-data över en tråd, men det är möjligt för en serializer att hantera vilket format som helst (textbaserat eller inte).

Se även

Om du bara vill få lite data från dina tabeller till en serialiserad form kan du använda kommandot `dumpdata`.

## Serialisering av data

På den högsta nivån kan du serialisera data så här:

    from django.core import serializers

    data = serializers.serialize("json", SomeModel.objects.all())

Argumenten till funktionen `serialize` är formatet att serialisera data till (se Serialiseringsformat) och en `QuerySet` att serialisera. (Egentligen kan det andra argumentet vara vilken iterator som helst som ger Django-modellinstanser, men det kommer nästan alltid att vara en QuerySet).

django.core.serializers.get_serializer(format)

Du kan också använda ett serializer-objekt direkt:

    JSONSerializer = serializers.get_serializer("json")
    json_serializer = JSONSerializer()
    json_serializer.serialize(queryset)
    data = json_serializer.getvalue()

Detta är användbart om du vill serialisera data direkt till ett filliknande objekt (som innehåller en `HttpResponse`):

    with open("file.json", "w") as out:
        json_serializer.serialize(SomeModel.objects.all(), stream=out)

Observera

Anrop av `get_serializer()` med en okänd format kommer att ge upphov till ett `django.core.serializers.SerializerDoesNotExist` undantag.

### Delmängd av fält

Om du bara vill att en delmängd av fälten ska serialiseras kan du ange ett `fields`-argument till serializer:

    from django.core import serializers

    data = serializers.serialize("json", SomeModel.objects.all(), fields=["name", "size"])

I det här exemplet serialiseras endast attributen `name` och `size` för varje modell. Primärnyckeln serialiseras alltid som elementet `pk` i resultatet; den visas aldrig i delen `fields`.

Observera

Beroende på din modell kan det hända att det inte går att deserialisera en modell som bara serialiserar en delmängd av sina fält. Om ett serialiserat objekt inte anger alla fält som krävs av en modell kommer deserialiseraren inte att kunna spara deserialiserade instanser.

### Nedärvda modeller

Om du har en modell som definieras med hjälp av en abstrakt basklass behöver du inte göra något särskilt för att serialisera den modellen. Anropa serialiseraren på det objekt (eller de objekt) som du vill serialisera, så kommer utdata att vara en fullständig representation av det serialiserade objektet.

Men om du har en modell som använder multi-table inheritance, måste du också serialisera alla basklasser för modellen. Detta beror på att endast de fält som är lokalt definierade i modellen kommer att serialiseras. Tänk till exempel på följande modeller:

    class Place(models.Model):
        name = models.CharField(max_length=50)

    class Restaurant(Place):
        serves_hot_dogs = models.BooleanField(default=False)

Om du bara serialiserar restaurangmodellen:

    data = serializers.serialize("json", Restaurant.objects.all())

fälten på den serialiserade utdata kommer endast att innehålla attributet `serves_hot_dogs`. Attributet `name` för basklassen kommer att ignoreras.

För att fullt ut kunna serialisera dina `Restaurant`-instanser måste du också serialisera `Place`-modellerna:

    all_objects = [*Restaurant.objects.all(), *Place.objects.all()]
    data = serializers.serialize("json", all_objects)

## Deserialisering av data

Deserialisering av data är mycket likt serialisering av dem:

    for obj in serializers.deserialize("json", data):
        do_something_with(obj)

Som du kan se tar funktionen `deserialize` samma formatargument som `serialize`, en sträng eller dataström, och returnerar en iterator.

Här blir det dock något komplicerat. De objekt som returneras av `deserialize` iterator är inte vanliga Django-objekt. Istället är de speciella `DeserializedObject`-instanser som omsluter ett skapat - men osparat - objekt och alla associerade relationsdata.

Genom att anropa `DeserializedObject.save()` sparas objektet i databasen.

Observera

Om attributet `pk` i de serialiserade uppgifterna inte finns eller är null, sparas en ny instans i databasen.

Detta säkerställer att deserialisering är en icke-destruktiv operation även om data i din serialiserade representation inte matchar vad som för närvarande finns i databasen. Vanligtvis ser arbetet med dessa `DeserializedObject`-instanser ut ungefär som:

    for deserialized_object in serializers.deserialize("json", data):
        if object_should_be_saved(deserialized_object):
            deserialized_object.save()

Med andra ord är den vanliga användningen att undersöka de deserialiserade objekten för att se till att de är ”lämpliga” att spara innan man gör det. Om du litar på din datakälla kan du istället spara objektet direkt och gå vidare.

Django-objektet i sig kan inspekteras som `deserialized_object.object`. Om fält i de serialiserade data inte finns på en modell, kommer ett `DeserializationError` att uppstå om inte `ignorenonexistent` argumentet skickas in som `True`:

    serializers.deserialize("json", data, ignorenonexistent=True)

## Format för serialisering

Django stöder ett antal serialiseringsformat, varav vissa kräver att du installerar Python-moduler från tredje part:

Identifierare | Information
--- | ---
`xml` | Serialiserar till och från en enkel XML-dialekt.
`json` | Serialiserar till och från JSON.
`jsonl` | Serialiserar till och från JSONL.
`yaml` | Serialiserar till YAML (YAML är inte ett märkspråk). Denna serialiserare är endast tillgänglig om PyYAML är installerat.

### XML

Det grundläggande XML-serialiseringsformatet ser ut så här:

    <?xml version="1.0" encoding="utf-8"?>
    <django-objects version="1.0">
        <object pk="123" model="sessions.session">
            <field type="DateTimeField" name="expire_date">2013-01-16T08:16:59.844560+00:00</field>
            <!-- ... -->
        </object>
    </django-objects>

Hela samlingen av objekt som antingen serialiseras eller deserialiseras representeras av en `<django-objects>`-tagg som innehåller flera `<object>`-element. Varje sådant objekt har två attribut: ”pk” och ”model”, där det senare representeras av appens namn (”sessions”) och modellens namn (”session”) med gemener, åtskilda av en punkt.

Varje fält i objektet serialiseras som ett `<field>`-element med fälten ”type” och ”name”. Elementets textinnehåll representerar det värde som ska lagras.

Utländska nycklar och andra relationsfält behandlas på ett lite annorlunda sätt:

    <object pk="27" model="auth.permission">
        <!-- ... -->
        <field to="contenttypes.contenttype" name="content_type" rel="ManyToOneRel">9</field>
        <!-- ... -->
    </object>

I det här exemplet anger vi att objektet `auth.Permission` med PK 27 har en främmande nyckel till instansen `contenttypes.ContentType` med PK 9.

ManyToMany-relationer exporteras för den modell som binder dem. Till exempel har modellen `auth.User` en sådan relation till modellen `auth.Permission`:

    <object pk="1" model="auth.user">
        <!-- ... -->
        <field to="auth.permission" name="user_permissions" rel="ManyToManyRel">
            <object pk="46"></object>
            <object pk="47"></object>
        </field>
    </object>

I det här exemplet kopplas den angivna användaren till behörighetsmodellerna med PK 46 och 47.

Kontrollera tecken

Om innehållet som skall serialiseras innehåller kontrolltecken som inte accepteras i XML 1.0-standarden, kommer serialiseringen att misslyckas med ett `ValueError`-undantag. Läs även W3C:s förklaring av HTML, XHTML, XML and Control Codes.

### JSON

Om vi fortsätter med samma exempel på data som tidigare skulle de serialiseras som JSON på följande sätt:

    [
        {
            "pk": "4b678b301dfd8a4e0dad910de3ae245b",
            "model": "sessions.session",
            "fields": {
                "expire_date": "2013-01-16T08:16:59.844Z",
                # ...
            },
        }
    ]

Formateringen här är lite enklare än med XML. Hela samlingen representeras bara som en array och objekten representeras av JSON-objekt med tre egenskaper: ”pk”, ”model” och ”fields”. ”fields” är återigen ett objekt som innehåller varje fälts namn och värde som property respektive property-value.

Foreign keys har PK för det länkade objektet som egenskapsvärde. ManyToMany-relationer serialiseras för den modell som definierar dem och representeras som en lista med PK:er.

Var medveten om att inte alla Django-utdata kan skickas oförändrade till `json`. Om du till exempel har någon anpassad typ i ett objekt som ska serialiseras, måste du skriva en anpassad `json`-kodare för det. Något liknande detta kommer att fungera:

    from django.core.serializers.json import DjangoJSONEncoder

    class LazyEncoder(DjangoJSONEncoder):
        def default(self, obj):
            if isinstance(obj, YourCustomType):
                return str(obj)
            return super().default(obj)

Du kan sedan skicka `cls=LazyEncoder` till funktionen `serializers.serialize()`:

    from django.core.serializers import serialize

    serialize("json", SomeModel.objects.all(), cls=LazyEncoder)

Observera också att GeoDjango tillhandahåller en customized GeoJSON serializer.

#### `DjangoJSONEncoder`

class django.core.serializers.json.DjangoJSONEncoder

JSON-serialisatorn använder `DjangoJSONEncoder` för kodning. Den är en underklass till `JSONEncoder` och hanterar dessa ytterligare typer:

`datetime`

  En sträng av formen `YYYY-MM-DDTHH:mm:ss.sssZ` eller `YYY-MM-DDTHH:mm:ss.sss+HH:MM` enligt definitionen i ECMA-262.

`date`

  En sträng av formen `YYYY-MM-DD` enligt definitionen i ECMA-262.

`time`

  En sträng av formen `HH:MM:ss.sss` enligt definitionen i ECMA-262.

`timedelta`

  En sträng som representerar en varaktighet enligt definitionen i ISO-8601. Till exempel representeras `timedelta(days=1, hours=2, seconds=3.4)` som `'P1DT02H00M03.400000S'`.

`Decimal`, `Promise` (`django.utils.functional.lazy()` objekt), `UUID`

  En strängrepresentation av objektet.

### JSONL

JSONL står för JSON Lines. I det här formatet separeras objekt med nya rader och varje rad innehåller ett giltigt JSON-objekt. JSONL-serialiserade data ser ut så här:

    {"pk": "4b678b301dfd8a4e0dad910de3ae245b", "model": "sessions.session", "fields": {...}}
    {"pk": "88bea72c02274f3c9bf1cb2bb8cee4fc", "model": "sessions.session", "fields": {...}}
    {"pk": "9cf0e26691b64147a67e2a9f06ad7a53", "model": "sessions.session", "fields": {...}}

JSONL kan vara användbart för att fylla på stora databaser, eftersom data kan bearbetas rad för rad i stället för att laddas in i minnet på en gång.

### YAML

YAML-serialisering ser ganska lik ut som JSON. Objektlistan serialiseras som en sekvens mappningar med nycklarna ”pk”, ”model” och ”fields”. Varje fält är återigen en mappning där nyckeln är namnet på fältet och värdet är värdet:

    - model: sessions.session
      pk: 4b678b301dfd8a4e0dad910de3ae245b
      fields:
        expire_date: 2013-01-16 08:16:59.844560+00:00

Referensfält representeras återigen av PK eller en sekvens av PK.

### Anpassade serialiseringsformat

Förutom standardformaten kan du skapa ett anpassat serialiseringsformat.

Låt oss till exempel titta på en serializer och deserializer för csv. Definiera först en klass för `Serializer` och en för `Deserializer`. Dessa kan åsidosätta befintliga serialiseringsformatklasser:

`väg/till/custom_csv_serializer.py`

     import csv

     from django.apps import apps
     from django.core import serializers
     from django.core.serializers.base import DeserializationError

     class Serializer(serializers.python.Serializer):
         def get_dump_object(self, obj):
             dumped_object = super().get_dump_object(obj)
             row = [dumped_object["model"], str(dumped_object["pk"])]
             row += [str(value) for value in dumped_object["fields"].values()]
             return ",".join(row), dumped_object["model"]

         def end_object(self, obj):
             dumped_object_str, model = self.get_dump_object(obj)
             if self.first:
                 fields = [field.name for field in apps.get_model(model)._meta.fields]
                 header = ",".join(fields)
                 self.stream.write(f"model,{header}\n")
             self.stream.write(f"{dumped_object_str}\n")

         def getvalue(self):
             return super(serializers.python.Serializer, self).getvalue()

     class Deserializer(serializers.python.Deserializer):
         def __init__(self, stream_or_string, **options):
             if isinstance(stream_or_string, bytes):
                 stream_or_string = stream_or_string.decode()
             if isinstance(stream_or_string, str):
                 stream_or_string = stream_or_string.splitlines()
             try:
                 objects = csv.DictReader(stream_or_string)
             except Exception as exc:
                 raise DeserializationError() from exc
             super().__init__(objects, **options)

         def _handle_object(self, obj):
             try:
                 model_fields = apps.get_model(obj["model"])._meta.fields
                 obj["fields"] = {
                     field.name: obj[field.name]
                     for field in model_fields
                     if field.name in obj
                 }
                 yield from super()._handle_object(obj)
             except (GeneratorExit, DeserializationError):
                 raise
             except Exception as exc:
                 raise DeserializationError(f"Error deserializing object: {exc}") from exc

Lägg sedan till modulen som innehåller serializer-definitionerna i din `SERIALIZATION_MODULES` setting:

    SERIALIZATION_MODULES = {
        "csv": "path.to.custom_csv_serializer",
        "json": "django.core.serializers.json",
    }

Changed in Django 5.2:

En klassdefinition för `Deserializer` har lagts till för vart och ett av de serialiseringsformat som tillhandahålls.

## Naturliga nycklar

Standardstrategin för serialisering av främmande nycklar och många-till-många-relationer är att serialisera värdet på primärnyckeln för objekten i relationen. Denna strategi fungerar bra för de flesta objekt, men den kan orsaka problem under vissa omständigheter.

Tänk på fallet med en lista över objekt som har en främmande nyckel som refererar till `ContentType`. Om du ska serialisera ett objekt som hänvisar till en innehållstyp måste du ha ett sätt att hänvisa till den innehållstypen till att börja med. Eftersom `ContentType`-objekt automatiskt skapas av Django under databassynkroniseringsprocessen är primärnyckeln för en viss innehållstyp inte lätt att förutsäga; det beror på hur och när `migrate` kördes. Detta gäller för alla modeller som automatiskt genererar objekt, särskilt inklusive `Permission`, `Group` och `User`.

Varning

Du bör aldrig inkludera automatiskt genererade objekt i en fixtur eller andra serialiserade data. Av en slump kan de primära nycklarna i fixturen matcha dem i databasen och laddning av fixturen kommer inte att ha någon effekt. I det mer sannolika fallet att de inte matchar, kommer fixturladdningen att misslyckas med ett `IntegrityError`.

Det är också en fråga om bekvämlighet. Ett heltals-id är inte alltid det mest praktiska sättet att referera till ett objekt; ibland skulle en mer naturlig referens vara till hjälp.

Det är av dessa skäl som Django tillhandahåller naturliga nycklar. En naturlig nyckel är en tupel av värden som kan användas för att unikt identifiera en objektinstans utan att använda det primära nyckelvärdet.

### Deserialisering av naturliga nycklar

Tänk på följande två modeller:

    from django.db import models

    class Person(models.Model):
        first_name = models.CharField(max_length=100)
        last_name = models.CharField(max_length=100)

        birthdate = models.DateField()

        class Meta:
            constraints = [
                models.UniqueConstraint(
                    fields=["first_name", "last_name"],
                    name="unique_first_last_name",
                ),
            ]

    class Book(models.Model):
        name = models.CharField(max_length=100)
        author = models.ForeignKey(Person, on_delete=models.CASCADE)

Normalt skulle serialiserade data för `Book` använda ett heltal för att hänvisa till författaren. I JSON kan en bok t.ex. serialiseras som:

    ...
    {"pk": 1, "model": "store.book", "fields": {"name": "Mostly Harmless", "author": 42}}
    ...

Det här är inte ett särskilt naturligt sätt att hänvisa till en författare. Det kräver att du känner till det primära nyckelvärdet för författaren; det kräver också att detta primära nyckelvärde är stabilt och förutsägbart.

Men om vi lägger till naturlig nyckelhantering i Person blir fixturen mycket mer human. För att lägga till hantering av naturliga nycklar definierar du en standardhanterare för Person med en `get_by_natural_key()`-metod. I fallet med en Person kan en bra naturlig nyckel vara paret av för- och efternamn:

    from django.db import models

    class PersonManager(models.Manager):
        def get_by_natural_key(self, first_name, last_name):
            return self.get(first_name=first_name, last_name=last_name)

    class Person(models.Model):
        first_name = models.CharField(max_length=100)
        last_name = models.CharField(max_length=100)
        birthdate = models.DateField()

        objects = PersonManager()

        class Meta:
            constraints = [
                models.UniqueConstraint(
                    fields=["first_name", "last_name"],
                    name="unique_first_last_name",
                ),
            ]

Nu kan böcker använda den naturliga nyckeln för att hänvisa till `Person`-objekt:

    ...
    {
        "pk": 1,
        "model": "store.book",
        "fields": {"name": "Mostly Harmless", "author": ["Douglas", "Adams"]},
    }
    ...

När du försöker ladda dessa serialiserade data kommer Django att använda metoden `get_by_natural_key()` för att lösa `["Douglas", "Adams"]` till primärnyckeln för ett faktiskt `Person`-objekt.

Observera

Oavsett vilka fält du använder för en naturlig nyckel måste de kunna identifiera ett objekt på ett unikt sätt. Detta innebär vanligtvis att din modell kommer att ha en unikhetsklausul (antingen `unique=True` på ett enda fält, eller en `UniqueConstraint` eller `unique_together` över flera fält) för fältet eller fälten i din naturliga nyckel. Unikhet behöver dock inte genomdrivas på databasnivå. Om du är säker på att en uppsättning fält kommer att vara effektivt unika kan du fortfarande använda dessa fält som en naturlig nyckel.

Deserialisering av objekt utan primärnyckel kontrollerar alltid om modellens manager har en `get_by_natural_key()`-metod och om så är fallet används den för att fylla i det deserialiserade objektets primärnyckel.

### Serialisering av naturliga nycklar

Så hur får man Django att ge ut en naturlig nyckel när man serialiserar ett objekt? För det första måste du lägga till en annan metod - den här gången till själva modellen:

    class Person(models.Model):
        first_name = models.CharField(max_length=100)
        last_name = models.CharField(max_length=100)
        birthdate = models.DateField()

        objects = PersonManager()

        class Meta:
            constraints = [
                models.UniqueConstraint(
                    fields=["first_name", "last_name"],
                    name="unique_first_last_name",
                ),
            ]

        def natural_key(self):
            return (self.first_name, self.last_name)

Den metoden ska alltid returnera en tupel med naturliga nycklar - i det här exemplet `(förnamn, efternamn)`. När du sedan anropar `serializers.serialize()` ger du argumenten `use_natural_foreign_keys=True` eller `use_natural_primary_keys=True`:

    >>> serializers.serialize(
    ...     "json",
    ...     [book1, book2],
    ...     indent=2,
    ...     use_natural_foreign_keys=True,
    ...     use_natural_primary_keys=True,
    ... )

När `use_natural_foreign_keys=True` anges kommer Django att använda metoden `natural_key()` för att serialisera alla främmande nyckelreferenser till objekt av den typ som definierar metoden.

När `use_natural_primary_keys=True` anges kommer Django inte att tillhandahålla den primära nyckeln i de serialiserade data för detta objekt eftersom den kan beräknas under deserialisering:

    ...
    {
        "model": "store.person",
        "fields": {
            "first_name": "Douglas",
            "last_name": "Adams",
            "birth_date": "1952-03-11",
        },
    }
    ...

Detta kan vara användbart när du behöver ladda serialiserade data i en befintlig databas och du inte kan garantera att det serialiserade primärnyckelvärdet inte redan används, och inte behöver säkerställa att deserialiserade objekt behåller samma primärnycklar.

Om du använder `dumpdata` för att generera serialiserade data kan du använda kommandoradsflaggorna `dumpdata --natural-foreign` och `dumpdata --natural-primary` för att generera naturliga nycklar.

Observera

Du behöver inte definiera både `natural_key()` och `get_by_natural_key()`. Om du inte vill att Django ska mata ut naturliga nycklar under serialisering, men du vill behålla möjligheten att ladda naturliga nycklar, kan du välja att inte implementera metoden `natural_key()`.

Omvänt, om du (av någon konstig anledning) vill att Django ska mata ut naturliga nycklar under serialisering, men inte kunna ladda dessa nyckelvärden, definierar du bara inte metoden `get_by_natural_key()`.

### Naturliga nycklar och framåtriktade referenser

Ibland när du använder natural foreign keys behöver du deserialisera data där ett objekt har en främmande nyckel som refererar till ett annat objekt som ännu inte har deserialiserats. Detta kallas för en ”framåtriktad referens”.

Anta t.ex. att du har följande objekt i din fixtur:

    ...
    {
        "model": "store.book",
        "fields": {"name": "Mostly Harmless", "author": ["Douglas", "Adams"]},
    },
    ...
    {"model": "store.person", "fields": {"first_name": "Douglas", "last_name": "Adams"}},
    ...

För att hantera denna situation måste du skicka `handle_forward_references=True` till `serializers.deserialize()`. Detta kommer att ställa in attributet `deferred_fields` på `DeserializedObject`-instanser. Du kommer att behöva hålla reda på `DeserializedObject` instanser där detta attribut inte är `None` och senare anropa `save_deferred_fields()` på dem.

Typisk användning ser ut så här:

    objs_with_deferred_fields = []

    for obj in serializers.deserialize("json", data, handle_forward_references=True):
        obj.save()
        if obj.deferred_fields is not None:
            objs_with_deferred_fields.append(obj)

    for obj in objs_with_deferred_fields:
        obj.save_deferred_fields()

För att detta ska fungera måste `ForeignKey` på referensmodellen ha `null=True`.

### Beroenden under serialisering

Det är ofta möjligt att undvika att uttryckligen behöva hantera framåtriktade referenser genom att vara försiktig med ordningsföljden för objekt inom en fixtur.

För att hjälpa till med detta kommer anrop till `dumpdata` som använder alternativet `dumpdata --natural-foreign` att serialisera alla modeller med en `natural_key()`-metod före serialisering av vanliga primärnyckelobjekt.

Detta kanske dock inte alltid är tillräckligt. Om din naturliga nyckel hänvisar till ett annat objekt (genom att använda en främmande nyckel eller en naturlig nyckel till ett annat objekt som en del av en naturlig nyckel), måste du kunna säkerställa att de objekt som en naturlig nyckel är beroende av förekommer i de serialiserade data innan den naturliga nyckeln kräver dem.

För att kontrollera denna ordning kan du definiera beroenden på dina `natural_key()`-metoder. Detta gör du genom att ställa in ett `dependencies` attribut på själva `natural_key()` metoden.

Låt oss till exempel lägga till en naturlig nyckel i modellen `Book` från exemplet ovan:

    class Book(models.Model):
        name = models.CharField(max_length=100)
        author = models.ForeignKey(Person, on_delete=models.CASCADE)

        def natural_key(self):
            return (self.name,) + self.author.natural_key()

Den naturliga nyckeln för en `Book` är en kombination av dess namn och dess författare. Detta innebär att `Person` måste serialiseras före `Book`. För att definiera detta beroende lägger vi till en extra rad:

    def natural_key(self):
        return (self.name,) + self.author.natural_key()

    natural_key.dependencies = ["example_app.person"]

Denna definition säkerställer att alla `Person`-objekt serialiseras före alla `Book`-objekt. I sin tur kommer alla objekt som refererar till `Book` att serialiseras efter att både `Person` och `Book` har serialiserats.