# Django 5.2.8 documentation

# Ramverket för innehållstyper

Django innehåller en `contenttypes`-applikation som kan spåra alla modeller som är installerade i ditt Django-drivna projekt, vilket ger ett generiskt gränssnitt på hög nivå för att arbeta med dina modeller.

## Översikt

Kärnan i contenttypes-applikationen är modellen `ContentType`, som finns i `django.contrib.contenttypes.models.ContentType`. Instanser av `ContentType` representerar och lagrar information om de modeller som är installerade i ditt projekt, och nya instanser av `ContentType` skapas automatiskt när nya modeller installeras.

Instanser av `ContentType` har metoder för att returnera de modellklasser de representerar och för att fråga objekt från dessa modeller. `ContentType` har också en custom manager som lägger till metoder för att arbeta med `ContentType` och för att erhålla instanser av `ContentType` för en viss modell.

Relationer mellan dina modeller och `ContentType` kan också användas för att aktivera ”generiska” relationer mellan en instans av en av dina modeller och instanser av alla modeller du har installerat.

## Installera ramverket för contenttypes

Contenttypes-ramverket ingår i standard `INSTALLED_APPS`-listan som skapats av `django-admin startproject`, men om du har tagit bort det eller om du manuellt ställer in din `INSTALLED_APPS`-lista kan du aktivera det genom att lägga till `'django.contrib.contenttypes'` till din `INSTALLED_APPS`-inställning.

Det är i allmänhet en bra idé att ha contenttypes-ramverket installerat; flera av Djangos andra medföljande applikationer kräver det:

- Admin-programmet använder den för att logga historiken för varje objekt som läggs till eller ändras via admin-gränssnittet.

- Djangos `autentiseringsramverk` använder det för att knyta användarrättigheter till specifika modeller.

## Modellen `ContentType` (innehållstyp)

class ContentType

  Varje instans av `ContentType` har två fält som tillsammans ger en unik beskrivning av en installerad modell:

  app_label

    Namnet på den applikation som modellen är en del av. Detta tas från `app_label`-attributet för modellen och inkluderar endast den sista delen av applikationens Python-importväg; `django.contrib.contenttypes`, till exempel, blir en `app_label` av `contenttypes`.

  model

    Namnet på modellklassen.

  Dessutom är följande egendom tillgänglig:

  name

    Det mänskliga läsbara namnet på innehållstypen. Detta hämtas från attributet `verbose_name` i modellen.

Låt oss titta på ett exempel för att se hur detta fungerar. Om du redan har `contenttypes`-programmet installerat, och sedan lägger till `the sites application` till din `INSTALLED_APPS`-inställning och kör `manage.py migrate` för att installera det, kommer modellen `django.contrib.sites.models.Site` att installeras i din databas. Tillsammans med det kommer en ny instans av `ContentType` att skapas med följande värden:

- `app_label` kommer att sättas till `'sites'` (den sista delen av Python-sökvägen `django.contrib.sites`).

- `model` kommer att sättas till `'site'`.

## Metoder för instanser av `ContentType`

Varje `ContentType`-instans har metoder som gör att du kan komma från en `ContentType`-instans till den modell den representerar, eller för att hämta objekt från den modellen:

ContentType.get_object_for_this_type(using=None, **kwargs)

  Tar en uppsättning giltiga uppslagsargument för den modell som `ContentType` representerar, och gör `en get()-uppslagning` på den modellen och returnerar motsvarande objekt. Argumentet `using` kan användas för att ange en annan databas än standarddatabasen.

ContentType.model_class()

  Returnerar den modellklass som representeras av denna `ContentType`-instans.

Vi kan till exempel leta upp `ContentType` för modellen `User`:

    >>> from django.contrib.contenttypes.models import ContentType
    >>> user_type = ContentType.objects.get(app_label="auth", model="user")
    >>> user_type
    <ContentType: user>

Och sedan använda den för att fråga efter en viss `User`, eller för att få tillgång till modellklassen `User`:

    >>> user_type.model_class()
    <class 'django.contrib.auth.models.User'>
    >>> user_type.get_object_for_this_type(username="Guido")
    <User: Guido>

Tillsammans möjliggör `get_object_for_this_type()` och `model_class()` två extremt viktiga användningsfall:

1. Med hjälp av dessa metoder kan du skriva generisk kod på hög nivå som utför frågor på alla installerade modeller - istället för att importera och använda en enda specifik modellklass kan du skicka en `app_label` och `model` till en `ContentType`-uppslagning vid körning och sedan arbeta med modellklassen eller hämta objekt från den.

2. Du kan relatera en annan modell till `ContentType` som ett sätt att binda instanser av den till särskilda modellklasser, och använda dessa metoder för att få åtkomst till dessa modellklasser.

Flera av Djangos medföljande applikationer använder sig av den senare tekniken. Till exempel: använder `behörighetssystemet` i Djangos autentiseringsramverk en `Permission`-modell med en främmande nyckel till `ContentType`; detta låter `Permission` representera koncept som ”kan lägga till blogginlägg” eller ”kan ta bort nyhetsartikel”.

### Funktionen ”ContentTypeManager

class ContentTypeManager

  `ContentType` har också en anpassad manager, `ContentTypeManager`, som lägger till följande metoder:

  clear_cache()

    Rensar en intern cache som används av `ContentType` för att hålla reda på modeller för vilka den har skapat `ContentType`-instanser. Du kommer förmodligen aldrig att behöva anropa den här metoden själv; Django kommer att anropa den automatiskt när den behövs.

  get_for_id(id)

    Leta upp en `ContentType` efter ID. Eftersom denna metod använder samma delade cache som `get_for_model()`, är det att föredra att använda denna metod framför den vanliga `ContentType.objects.get(pk=id)`

  get_for_model(model, for_concrete_model=True)

    Tar antingen en modellklass eller en instans av en modell och returnerar `ContentType`-instansen som representerar den modellen. `for_concrete_model=False` tillåter hämtning av `ContentType` för en proxymodell.

  get_for_models(*models, for_concrete_models=True)

    Tar ett variabelt antal modellklasser och returnerar en ordbok som mappar modellklasserna till `ContentType`-instanser som representerar dem. `for_concrete_models=False` tillåter hämtning av `ContentType` för proxymodeller.

  get_by_natural_key(app_label, model)

    Returnerar `ContentType`-instansen som identifieras unikt av den angivna applikationsetiketten och modellnamnet. Det primära syftet med denna metod är att tillåta att `ContentType`-objekt refereras via en naturlig nyckel under deserialisering.

The `get_for_model()` method is especially useful when you know you need to work with a `ContentType` but don’t want to go to the trouble of obtaining the model’s metadata to perform a manual lookup:

    >>> from django.contrib.auth.models import User
    >>> ContentType.objects.get_for_model(User)
    <ContentType: user>

## Generiska relationer

Genom att lägga till en främmande nyckel från en av dina egna modeller till `ContentType` kan din modell effektivt binda sig till en annan modellklass, som i exemplet med modellen `Permission` ovan. Men det är möjligt att gå ett steg längre och använda `ContentType` för att möjliggöra verkligt generiska (ibland kallade ”polymorfa”) relationer mellan modeller.

Det kan till exempel användas för ett taggningssystem på följande sätt:

    from django.contrib.contenttypes.fields import GenericForeignKey
    from django.contrib.contenttypes.models import ContentType
    from django.db import models

    class TaggedItem(models.Model):
        tag = models.SlugField()
        content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
        object_id = models.PositiveBigIntegerField()
        content_object = GenericForeignKey("content_type", "object_id")

        def __str__(self):
            return self.tag

        class Meta:
            indexes = [
                models.Index(fields=["content_type", "object_id"]),
            ]

En normal `ForeignKey` kan bara ”peka på” en annan modell, vilket innebär att om modellen `TaggedItem` använde en `ForeignKey` skulle den behöva välja en och endast en modell att lagra taggar för. Contenttypes-applikationen tillhandahåller en speciell fälttyp (`GenericForeignKey`) som kringgår detta och gör att relationen kan vara med vilken modell som helst:

class GenericForeignKey

  Det finns tre delar för att konfigurera en `GenericForeignKey`:

  1. Ge din modell en `ForeignKey` till `ContentType`. Det vanliga namnet för detta fält är ”content_type”.

  2. Ge din modell ett fält som kan lagra primära nyckelvärden från de modeller du kommer att relatera till. För de flesta modeller innebär detta en `PositiveBigIntegerField`. Det vanliga namnet för detta fält är ”object_id”.

  3. Ge din modell en `GenericForeignKey`, och skicka den namnen på de två fälten som beskrivs ovan. Om dessa fält heter ”content_type” och ”object_id” kan du utelämna detta - det är standardfältens namn som `GenericForeignKey` kommer att leta efter.

  Till skillnad från `ForeignKey`, skapas inte automatiskt ett databasindex för `GenericForeignKey`, så det rekommenderas att du använder `Meta.indexes` för att lägga till ditt eget index med flera kolumner. Detta beteende kan komma att ändras i framtiden.

  for_concrete_model

    Om `False`, kommer fältet att kunna referera till proxy-modeller. Standard är `True`. Detta speglar argumentet `for_concrete_model` till `get_for_model()`.

Kompatibilitet med primärnyckeltyp

Fältet ”object_id” behöver inte vara av samma typ som primärnyckelfälten i de relaterade modellerna, men deras primärnyckelvärden måste kunna kopplas till samma typ som fältet ”object_id” genom dess `get_db_prep_value()`-metod.

Om du t.ex. vill tillåta generiska relationer till modeller med antingen `IntegerField` eller `CharField` primärnyckelfält, kan du använda `CharField` för fältet ”object_id” i din modell eftersom heltal kan omvandlas till strängar med `get_db_prep_value()`.

För maximal flexibilitet kan du använda en `TextField` som inte har en maximal längd definierad, men detta kan medföra betydande prestandaförluster beroende på din databasbackend.

Det finns ingen universallösning för vilken fälttyp som är bäst. Du bör utvärdera de modeller som du förväntar dig att peka på och avgöra vilken lösning som är mest effektiv för ditt användningsfall.

Serialisering av referenser till `ContentType`-objekt

Om du serialiserar data (t.ex. när du genererar `fixtures`) från en modell som implementerar generiska relationer, bör du förmodligen använda en naturlig nyckel för att unikt identifiera relaterade `ContentType`-objekt. Se natural keys och `dumpdata --natural-foreign` för mer information.

Detta kommer att möjliggöra ett API som liknar det som används för en vanlig `ForeignKey`; varje `TaggedItem` kommer att ha ett `content_object`-fält som returnerar det objekt som det är relaterat till, och du kan också tilldela det fältet eller använda det när du skapar en `TaggedItem`:

    >>> from django.contrib.auth.models import User
    >>> guido = User.objects.get(username="Guido")
    >>> t = TaggedItem(content_object=guido, tag="bdfl")
    >>> t.save()
    >>> t.content_object
    <User: Guido>

Om det relaterade objektet tas bort, förblir fälten `content_type` och `object_id` inställda på sina ursprungliga värden och `GenericForeignKey` returnerar `None`:

    >>> guido.delete()
    >>> t.content_object  # returns None

På grund av hur `GenericForeignKey` implementeras kan du inte använda sådana fält direkt med filter (`filter()` och `exclude()`, till exempel) via databas-API:et. Eftersom en `GenericForeignKey` inte är ett normalt fältobjekt, kommer dessa exempel inte att fungera:

    # This will fail
    >>> TaggedItem.objects.filter(content_object=guido)
    # This will also fail
    >>> TaggedItem.objects.get(content_object=guido)

På samma sätt visas inte `GenericForeignKey`s i `ModelForm`s.

### Omvända generiska relationer

class GenericRelation
  related_query_name

    Relationen från det relaterade objektet tillbaka till detta objekt existerar inte som standard. Om du ställer in `related_query_name` skapas en relation från det relaterade objektet tillbaka till detta. Detta gör det möjligt att ställa frågor och filtrera från det relaterade objektet.

Om du vet vilka modeller du kommer att använda oftast kan du också lägga till en ”omvänd” generisk relation för att aktivera ytterligare ett API. Till exempel:

    from django.contrib.contenttypes.fields import GenericRelation
    from django.db import models

    class Bookmark(models.Model):
        url = models.URLField()
        tags = GenericRelation(TaggedItem)

”Bokmärkes”-instanser har alla ett ”tags”-attribut, som kan användas för att hämta deras associerade ”tagged items”:

    >>> b = Bookmark(url="https://www.djangoproject.com/")
    >>> b.save()
    >>> t1 = TaggedItem(content_object=b, tag="django")
    >>> t1.save()
    >>> t2 = TaggedItem(content_object=b, tag="python")
    >>> t2.save()
    >>> b.tags.all()
    <QuerySet [<TaggedItem: django>, <TaggedItem: python>]>

Du kan också använda `add()`, `create()` eller `set()` för att skapa relationer:

    >>> t3 = TaggedItem(tag="Web development")
    >>> b.tags.add(t3, bulk=False)
    >>> b.tags.create(tag="Web framework")
    <TaggedItem: Web framework>
    >>> b.tags.all()
    <QuerySet [<TaggedItem: django>, <TaggedItem: python>, <TaggedItem: Web development>, <TaggedItem: Web framework>]>
    >>> b.tags.set([t1, t3])
    >>> b.tags.all()
    <QuerySet [<TaggedItem: django>, <TaggedItem: Web development>]>

Anropet `remove()` raderar de angivna modellobjekten i bulk:

    >>> b.tags.remove(t3)
    >>> b.tags.all()
    <QuerySet [<TaggedItem: django>]>
    >>> TaggedItem.objects.all()
    <QuerySet [<TaggedItem: django>]>

Metoden `clear()` kan användas för att massradera alla relaterade objekt för en instans:

    >>> b.tags.clear()
    >>> b.tags.all()
    <QuerySet []>
    >>> TaggedItem.objects.all()
    <QuerySet []>

Genom att definiera `GenericRelation` med `related_query_name` kan man ställa frågor från det relaterade objektet:

    tags = GenericRelation(TaggedItem, related_query_name="bookmark")

Detta möjliggör filtrering, ordning och andra frågeoperationer på `Bookmark` från `TaggedItem`:

    >>> # Get all tags belonging to bookmarks containing `django` in the url
    >>> TaggedItem.objects.filter(bookmark__url__contains="django")
    <QuerySet [<TaggedItem: django>, <TaggedItem: python>]>

Om du inte lägger till `related_query_name` kan du göra samma typer av uppslagningar manuellt:

    >>> bookmarks = Bookmark.objects.filter(url__contains="django")
    >>> bookmark_type = ContentType.objects.get_for_model(Bookmark)
    >>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id, object_id__in=bookmarks)
    <QuerySet [<TaggedItem: django>, <TaggedItem: python>]>

Precis som `GenericForeignKey` accepterar namnen på fälten content-type och object-ID som argument, så gör även `GenericRelation` det; om modellen som har den generiska främmande nyckeln använder icke-standardnamn för dessa fält, måste du skicka namnen på fälten när du ställer in en `GenericRelation` till den. Om t.ex. modellen `TaggedItem` som nämns ovan använder fält med namnen `content_type_fk` och `object_primary_key` för att skapa sin generiska främmande nyckel, måste en `GenericRelation` tillbaka till den definieras på följande sätt:

    tags = GenericRelation(
        TaggedItem,
        content_type_field="content_type_fk",
        object_id_field="object_primary_key",
    )

Observera också att om du tar bort ett objekt som har en `GenericRelation`, kommer alla objekt som har en `GenericForeignKey` som pekar på det också att tas bort. I exemplet ovan innebär detta att om ett `Bookmark`-objekt raderas, kommer alla `TaggedItem`-objekt som pekar på det att raderas samtidigt.

Till skillnad från `ForeignKey` accepterar `GenericForeignKey` inte ett `on_delete`-argument för att anpassa detta beteende; om så önskas kan du undvika kaskadradering genom att inte använda `GenericRelation`, och alternativt beteende kan tillhandahållas via `pre_delete`-signalen.

### Generiska relationer och aggregering

Djangos API för databasaggregering fungerar med en `GenericRelation`. Du kan till exempel ta reda på hur många taggar alla bokmärken har:

    >>> Bookmark.objects.aggregate(Count("tags"))
    {'tags__count': 3}

### Generisk relation i formulär

Modulen `django.contrib.contenttypes.forms` tillhandahåller:

- `BaseGenericInlineFormSet`

- En formulärfabrik, `generic_inlineformset_factory()`, för användning med `GenericForeignKey`.

class BaseGenericInlineFormSet

generic_inlineformset_factory(model, form=ModelForm, formset=BaseGenericInlineFormSet, ct_field='content_type', fk_field='object_id', fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, validate_max=False, for_concrete_model=True, min_num=None, validate_min=False, absolute_max=None, can_delete_extra=True)

  Returnerar en `GenericInlineFormSet` med `modelformset_factory()`.

  Du måste ange `ct_field` och `fk_field` om de skiljer sig från standardvärdena, `content_type` respektive `object_id`. Andra parametrar liknar de som dokumenteras i `modelformset_factory()` och `inlineformset_factory()`.

  Argumentet `for_concrete_model` motsvarar argumentet `for_concrete_model` på `GenericForeignKey`.

### Generiska relationer inom administration

Modulen `django.contrib.contenttypes.admin` tillhandahåller `GenericTabularInline` och `GenericStackedInline` (underklasser till `GenericInlineModelAdmin`)

Dessa klasser och funktioner gör det möjligt att använda generiska relationer i formulär och i admin. Se dokumentationen model formset och admin för mer information.

class GenericInlineModelAdmin

  Klassen `GenericInlineModelAdmin` ärver alla egenskaper från klassen `InlineModelAdmin`. Den lägger dock till ett par egna för att arbeta med den generiska relationen:

  ct_field

    Namnet på `ContentType` främmande nyckelfält på modellen. Standardvärdet är `content_type`.

  ct_fk_field

    Namnet på det heltalsfält som representerar ID:t för det relaterade objektet. Standardvärdet är `object_id`.

class GenericTabularInline

class GenericStackedInline

  Underklasser till `GenericInlineModelAdmin` med staplad respektive tabulär layout.

### `GeneriskPrefetch()`

class GenericPrefetch(lookup, querysets, to_attr=None)

Denna sökning liknar `Prefetch()` och den bör endast användas på `GenericForeignKey`. Argumentet `querysets` accepterar en lista med querysets, var och en för en annan `ContentType`. Detta är användbart för `GenericForeignKey` med icke-homogena uppsättningar resultat.

    >>> from django.contrib.contenttypes.prefetch import GenericPrefetch
    >>> bookmark = Bookmark.objects.create(url="https://www.djangoproject.com/")
    >>> animal = Animal.objects.create(name="lion", weight=100)
    >>> TaggedItem.objects.create(tag="great", content_object=bookmark)
    >>> TaggedItem.objects.create(tag="awesome", content_object=animal)
    >>> prefetch = GenericPrefetch(
    ...     "content_object", [Bookmark.objects.all(), Animal.objects.only("name")]
    ... )
    >>> TaggedItem.objects.prefetch_related(prefetch).all()
    <QuerySet [<TaggedItem: Great>, <TaggedItem: Awesome>]>