# dokumentasi Django 2.2.9.dev20191202104323

# Kerangka contenttypes

Django menyertakan sebuah aplikasi `contenttypes` yang dapat melacak semua model-model terpasang dalam proyek Django-powered anda, menyediakan tingkat-tinggi, antarmuka umum untuk bekerja dengan model-model anda.

## Ikhtisar

Di jantung dari aplikasi contenttype adalah model `ContentType`, yang tinggal di django.contrib.contenttypes.models.ContentType`. Instance dari `ContentType` mewakili dan menyimpan informasi tentang model-model terpasang dalam proyek anda, dan instance baru dari `ContentType` otomatis dibuat ketika model-model baru terpasang.

Instance dari `ContentType` mempunai metode-metode untuk mengembalikan kelas-kelas model mereka wakilkan dan untuk meminta obyek dari model-model itu. `ContentType` juga mempunyai sebuah custom manager 1 yang menambahkan metode untuk bekerja dengan `ContentType` dan untuk mendapatkan instance dari `ContentType` untuk model tertentu.

Hubungan diantara model-model anda dan `ContentType` dapat juga digunakan untuk mengadakan hubungan "umum" diantara sebuah instance dari satu dari model-model anda dan instance dari model apapun anda telah pasang.

## Memasang kerangka contenttypes

Kerangka kerja contenttype disertakan dalam daftar `INSTALLED_APPS` awalan dibuat oleh `django-admin startproject`, tetapi jika anda telah memindahkan itu atau jika anda secara manual menyetel daftar `INSTALLED_APPS` anda, anda dapat mengadakan itu dengan menambahkan `'django.contrib.contenttypes'` ke pengaturan `INSTALLED_APPS` anda.

Umumnya ide bagus memiliki kerangka contenttype terpasang; beberapa aplikasi gabungan lain Django membutuhkan itu:

- Apliaksi admin menggunakan itu utuk mencatat riwayat dari setiap obyek ditambahkan atau dirubah melalui antarmuka admin.
- `authentication framework` Django menggunakan itu untuk mengikat perizinan pengguna pada model-model tertentu.

## Model `ContentType`

class `ContentType`

  Setiap instance dari `ContentType` mempunyai dua bidang yang, diambil bersama-sama, secara unik menggambarkan sebuah model terpasang:

  `app_label`

    Nama dari aplikasi model adalah bagian darinya. Ini diambil dari atribut `app_label` dari model, dan menyertakan hanya bagian terakhir dari `django.contrib.contenttypes` jalur impor Python aplikasi, sebagai contoh, menjadi `app_label` dari `contenttypes`.

  `model`

    Nama dari kelas model.

  Sebagai tambahan, sifat berikut tersedia:

  `name`

    Nama dapat-dibaca-manusia dari jenis isi. Ini adalah diambil dari atribut `verbose_name` dari model.

Mari kita lihat sebuah contoh untuk melihat bagaimana ini bekerja. Jika anda seudah memiliki aplikasi `contenttypes` terpasang, dan kemudian tambah `the sites application` ke pengaturan `INSTALLED_APPS` anda dan menjalankan `manage.py migrate` untuk memasangnya, model `django.contrib.sites.models.Site` akan dipasang kedalam basisdata anda. Bersama dengan itu sebuah instance baru dari `ContentType` akan dibuat dengan nilai-nilai berikut:

- `app_label` akan disetel menjadi `'sites'` (bagian terakhir dari jalur Python `django.contrib.sites`).
- `model` akan disetel menjadi `'site'`.

## Metode pada instance `ContentType`

Setiap instance `ContentType` mempunyai metode-metode yang mengizinkan anda mendapatkan dari sebuah instance `ContentType` pada model yang itu wakili, atau untuk mengambil obyek-obyek dari model itu:

`ContentType.``get_object_for_this_type`(**kwargs)

  Mengambil sekumpulan dari perwakilan lookup arguments 1 for the model the `ContentType` sah, dan melakukan `a get() lookup` pada model itu, mengembalikan obyek yang sesuai.

`ContentType.``model_class`()

  Mengembalikan kelas model diwakilkan oleh instance `ContentType` ini.

Sebagai contoh, kami dapat mencari `ContentType` untuk model `User`:

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

Dan kemudian gunakan itu pada permintaan untuk `User` tertentu, atau untuk mendapatkan akses ke kelas model `User`:

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

Bersama-sama, meth:~django.contrib.contenttypes.models.ContentType.get_object_for_this_type dan `model_class()` mengadakan dua sangat penting penggunaan kasus:

1. Menggunakan metode ini, anda dapat menulis kode umum tingkat-tinggi yang melakukan permintaan pada mode terpasang apapun -- daripada mengimpor dan menggunakan kelas model khusus, anda dapat melewatkan sebuah `app_label` dan `model` kedalam sebuah pencarian `ContentType` pada waktu berjalan dan kemudian bekerja dengan kelas model atau mengambil obyek dari itu.
2. Anda dapat menghubungkan model lain ke `ContentType` sebagai sebuah cara dari mengikat instance dari itu ke kelas-kelas model tertentu, dan gunakan metode ini untuk mendapatkan akses ke kelas-kelas model tersebut.

Beberapa dari aplikasi gabungan Django membuat dari teknik terakhir. Sebagai contoh, `the permissions system` dalam kerangka kerja autentifikasi Django menggunakan model `Permission` dengan sebuah foreign key pada `ContentType`; ini membuat `Permission` mewakili konsep-konsep seperti "dapat menambah masukan blog" atau "dapat menghapus cerita berita".

### `ContentTypeManager`

class `ContentTypeManager`

  `ContentType` juga mempunyai pengelola penyesuaian, `ContentTypeManager`, yang menambahkan metode berikut:

  `clear_cache`()

    Bersihkan cache internal digunakan oleh `ContentType` untuk menjaga lintasan dari model-model untuk yang itu telah membuat instance `ContentType`. Anda mungkin tidak pernah butuh memanggil metode ini anda sendiri; Django akan memanggil itu secara otomatis ketika itu dibutuhkan.

  `get_for_id`(id)

    Pencarian `ContentType` berdasarkan ID. Sejak metode ini menggunakan cache dibagi yang sama seperti `get_for_model()`, itu lebih disukai untuk menggunakan metode ini terhadap `ContentType.objects.get(pk=id)` biasa

  `get_for_model`(model, for_concrete_model=True)

    Ambil antara sebuah kelas model atau sebuah instance dari model, dan kembalikan instance `ContentType` mewakili model itu. `for_concrete_model=False` mengizinkan mengambil `ContentType` dari model proxy.

  `get_for_models`(*models, for_concrete_models=True)

    Mengambil sejumlah variabel apapun dari kelas-kelas model, dan mengembalikan sebuah kamus memetakan kelas-kelas model pada instance `ContentType` mewakili mereka. `for_concrete_models=False` mengizinkan mengambil `ContentType` dari model proxy.

  `get_by_natural_key`(app_label, model)

    Mengembalikan instance `ContentType` secara unik dicirikan dengan label aplikasi yang diberikan dan nama model. Tujuan utama dari metode ini adalah mengizinkan obyek `ContentType` untuk diacukan melalui natural key1 selama deserialisasi.

Metode `get_for_model()` khususnya sangat berguna ketika anda mengetahui anda butuh bekerja dengan `ContentType` tetapi tidak ingin menjadi masalah dari mendapatkan metadata model untuk melakukan pencarian manual:

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

## Hubungan umum

Menambahkan sebuah foreign key dari satu dari model anda sendiri pada `ContentType` mengizinkan model anda secara efektif mengikat diri sendiri ke kelas model lain, seperti dalam contoh dari model `Permission` diatas. Tetapi itu memungkinkan pergi satu langkah lebih jauh dan menggunakan `ContentType` untuk mengadakan hubungan umum sebenarnya (terkadang disebut "polimorfik") diantara model.

Contoh sederhana adalah sistem etiket, yang mungkin kelihatan seperti ini:

    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.PositiveIntegerField()
        content_object = GenericForeignKey('content_type', 'object_id')

        def __str__(self):
            return self.tag

Sebuah `ForeignKey` biasa dapat hanya "menunjuk" satu model lain, yang berarti bahwa jika model `TaggedItem` menggunakan sebuah `ForeignKey` itu akan harus memilih satu dan hanya satu model untuk menyimpan etiket-etiket. Aplikasi contenttype menyediakan jenis bidang khusus (`GenericForeignKey`) yang memecahkan ini dan mengizinkan hubungan dengan model apapun.

class `GenericForeignKey`

  Terdapat tiga bagian untuk mengatur `GenericForeignKey`:

  1. Berikan model anda sebuah `ForeignKey` pada `ContentType`. Nama biasa untuk bidang ini adalah "content_type".
  2. Berikan model anda sebuah bidang yang dapat menyimpan nilai-nilai primary key dari model-model anda akan kaitkan. Untuk kebanyakan model, ini berarti `PositiveIntegerField`. Nama biasa untuk bidang ini adalah "object_id".
  3. Berikan model anda `GenericForeignKey`, dan lewatkan itu nama-nama dari dua bidang digambarkan diatas. Jika bidang-bidang ini bernama "content_type" dan "object_id", anda dapat mengabaikan ini --yaitu nama-nama bidang awalan `GenericForeignKey` akan mencari.
  `for_concrete_model`

    Jika `False`, bidang akan dapat mengacukan model-model proxy. Awalan adalah `True`. Ini mencerminkan argumen `for_concrete_model` pada `get_for_model()`.

Kesesuaian jenis primary key

Bidang "object_id" tidak harus mempunyai jenis sama sebagai bidang primary key pada model-model terkait, tetapi nilai-nilai primary key harus dapat dipaksa ke jenis sama sebagai bidang "object_id" dengan metode `get_db_prep_value()` nya.

Sebagai contoh, jika anda ingin mengizinkan hubungan umum pada model-model dengan salah satu primary key `IntegerField` atau `CharField`, anda dapat menggunakan `CharField` untuk bidang "object_id" pada model anda karena integer dapat dipaksa menjadi string oleh `get_db_prep_value()`.

Untuk keluwesan maksimal anda dapat menggunakan `TextField` yang tidak mempunyai panjang maksimal ditentukan, bagaimanapun ini mungkin mendatangkan denda penampilan yang berarti bergantung pada backend basisdata anda.

Tidak ada pemecahan satu-ukuran-cocok-semua untuk jenis bidang yang terbaik. Anda harus menilai model-model anda harapkan untuk ditunjuk dan menentukan pemecahan mana akan menjadi paling efektif untuk penggunaan kasus anda.

Menserialisasikan acuan pada obyek `ContentType`

Jika anda sedang menserialkan data(sebagai contoh, ketika membangkitkan `fixtures`) dari sebuah model yang menerapkan hubungan umum, anda harus mungkin menggunakan kunci alami pada secara unik mencirikan obyek `ContentType` terkait. Lihat natural keys1 and `dumpdata --natural-foreign` untuk informasi lebih.

Ini akan mengadakan sebuah API mitip pada satu digunakan untuk `ForeignKey`; biasa setiap `TaggedItem` akan mempunyai sebuah bidang `content_object` yang mengembalikan obyek yang terkait dengan, dan anda dapat juga menugaskan ke bidang itu atau menggunakan itu ketika membuat sebuah `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>

Jika obyek terkait dihapus, bidang `content_type` dan `object_id` masih menyetel ke nilai aslinya dan `GenericForeignKey` mengembalikan `None`:

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

Dikarenakan cara `GenericForeignKey` diterapkan, anda tidak dapat menggunakan bidang-bidang itu langsung dengan penyaring (`filter()` dan `exclude()`, sebagai contoh) melalui API basisdata. Karena `GenericForeignKey` bukan obyek bisang biasa, contoh-contoh ini akan tidak bekerja:

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

Juga, `GenericForeignKey` tidak muncul dalam `ModelForm`.

### Membalikkan hubungan umum

class `GenericRelation`
  `related_query_name`

    Hubungan pada obyek terkait kembali ke obyek ini tidak ada secara awalan. Pengaturan `related_query_name` membuat sebuah hubungan dari obyek terkait kembali ke satu ini. Ini mengizinkan meminta dan menyaring dari obyek terkait.

Jika anda mengetahui model-model mana anda akan menggunakan paling sering, anda dapat juga menambahkan hubungan umum "reverse" untuk mengadakan sebuah tambahan API. Sebagai contoh:

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

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

Instance `Bookmark` akan setipanya memiliki sebuah atribut `tags`, yang dapat digunakan untuk mengambil `TaggedItems` terkait mereka:

    >>> 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>]>

Menentukan `GenericRelation` dengan kumpulan `related_query_name` mengizinkan meminta dari obyek terkait:

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

Ini mengadakan penyaring, oengurutan, dan tindakan permintaan lain pada `Bookmark` dari `TaggedItem`:

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

Tentu saja, jika anda tidak menambah `related_query_name`, anda dapat melakukan jenis-jenis sama dari pencarian secara manual:

    >>> 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>]>

Sama seperti `GenericForeignKey` menerima nama-nama dari bidang content-type dan object-ID sebagai argumen, begitu juga `GenericRelation`; jika model yang mempunyai foreign key umum menggunakan nama bukan-awalan untuk bidang-bidang tersebut, anda harus melewatkan nama-nama dari bidang ketika mengatur sebuah `GenericRelation` untuk itu. Sebagai contoh, jika model `TaggedItem` mengacu pada diatas menggunakan bidang bernama `content_type_fk` dan `object_primary_key` untuk membuat foreign key umumnya, kemudian `GenericRelation` kembali ke itu akan butuh ditentukan seperti itu:

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

Catat juga, bahwa jika anda menghapus sebuah obyek yang mempunyai sebuah `GenericRelation`, obyek apapun yang mempunyai `GenericForeignKey` menunjuk ke itu akan dihapus juga. Dalam contoh diatas, ini berarti bahwa jika sebuah obyek `Bookmark` dihapus, obyek `TaggedItem` apapun menunjuk pada itu akan dihapus pada waktu yang sama.

Tidak seperti `ForeignKey`, `GenericForeignKey` tidak menerima sebuah argumen `on_delete` untuk menyesuaiakan perilaku ini; jika diinginkan anda dapat menghindari penghapusan-mengalir-ke-bawah cukup dengan tidak menggunakan `GenericRelation`, dan perilaku bergantian dapat disediakan melalui sinyal `pre_delete`.

### Hubungan umum dan pengumpulan

Django's database aggregation API bekerja dengan `GenericRelation`. Sebagai contoh, anda dapat menemukan berapa banyak etiket semua bookmark miliki:

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

### Hubungan umum di formulir

Modul `django.contrib.contenttypes.forms` menyediakan:

- `BaseGenericInlineFormSet`
- Pabrik formset, `generic_inlineformset_factory()`, untuk digunakan dengan `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)

  Mengembalikan `GenericInlineFormSet` menggunakan `modelformset_factory()`.

  Anda harus menyediakan `ct_field` dan `fk_field` jika mereka berbeda dari awalan, `content_type` dan `object_id` masing-masing. Parameter lain adalah mirip ke yang didokumentasi di `modelformset_factory()` dan `inlineformset_factory()`.

  Argumen `for_concrete_model` berhubungan ke argumen `for_concrete_model` pada `GenericForeignKey`.

### Hubungan umum di admin

Modul `django.contrib.contenttypes.admin` menyediakan `GenericTabularInline` dan `GenericStackedInline` (subkelas-subkelas dari `GenericInlineModelAdmin`)

Kelas-kelas dan fungsi-fungsi ini mengadakan penggunaan hubungan umum di formulir dan admin. Lihat dokumentasi model formset dan admin untuk informasi lebih.

class `GenericInlineModelAdmin`

  Kelas `GenericInlineModelAdmin` mewarisi semua sifat-sifat dari sebuah kelas `InlineModelAdmin`. Bagaimanapun, itu menambahkan sebuah pasang dari itu sendiri untuk bekerja dengan hubungan umum:

  `ct_field`

    Nama dari bidang foreign key `ContentType` pada model. Awalan pada `content_type`.

  `ct_fk_field`

    Nama dari bidang integer yang mewakili ID dari obyek terkait. Awalan pada `object_id`.

class `GenericTabularInline`

class `GenericStackedInline`

  Subkelas-subkelas dari `GenericInlineModelAdmin` dengan tata letak bertumpuk dan datar, masing-masing.