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.
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.
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:
authentication framework
Django menggunakan itu untuk mengikat perizinan pengguna pada model-model tertentu.ContentType
¶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:
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:
app_label
dan model
kedalam sebuah pencarian ContentType
pada waktu berjalan dan kemudian bekerja dengan kelas model atau mengambil obyek dari itu.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
¶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>
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.
Sebagai contoh, itu dapat digunakan untuk sistem pe etiketan seperti itu:
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
class Meta:
indexes = [
models.Index(fields=["content_type", "object_id"]),
]
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.
GenericForeignKey
¶Terdapat tiga bagian untuk mengatur GenericForeignKey
:
ForeignKey
pada ContentType
. Nama biasa untuk bidang ini adalah "content_type".PositiveIntegerField
. Nama biasa untuk bidang ini adalah "object_id".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.Unlike for the ForeignKey
, a database index is
not automatically created on the
GenericForeignKey
, so it's
recommended that you use
Meta.indexes
to add your own
multiple column index. This behavior may change in the
future.
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
.
GenericRelation
¶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>]>
You can also use add()
, create()
, or set()
to create
relationships:
>>> 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>]>
The remove()
call will bulk delete the specified model objects:
>>> b.tags.remove(t3)
>>> b.tags.all()
<QuerySet [<TaggedItem: django>]>
>>> TaggedItem.objects.all()
<QuerySet [<TaggedItem: django>]>
The clear()
method can be used to bulk delete all related objects for an
instance:
>>> b.tags.clear()
>>> b.tags.all()
<QuerySet []>
>>> TaggedItem.objects.all()
<QuerySet []>
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>]>
If you don't add the related_query_name
, you can do the same types of
lookups manually:
>>> 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.
Unlike ForeignKey
,
GenericForeignKey
does not accept
an on_delete
argument to customize this
behavior; if desired, you can avoid the cascade-deletion by not using
GenericRelation
, and alternate
behavior can be provided via the pre_delete
signal.
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}
Modul django.contrib.contenttypes.forms
menyediakan:
BaseGenericInlineFormSet
generic_inlineformset_factory()
, untuk digunakan dengan GenericForeignKey
.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)¶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
.
The absolute_max
and can_delete_extra
arguments were added.
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.
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
.
GenericTabularInline
¶GenericStackedInline
¶Subkelas-subkelas dari GenericInlineModelAdmin
dengan tata letak bertumpuk dan datar, masing-masing.
Agu 03, 2022