Pengelola¶
-
class
Manager
¶
Sebuah manager
adalah antarmuka melalui mana tindakan permintaan basisdata disediakan pada model Django. Setidaknya satu Manager
ada untuk setiap model dalam sebuah apliaksi Django.
Cara kelas-kelas Manager
bekerja didokumentasikan dalam Membuat query; dokumen ini secara khusus menyentuh pada pilihan model yang menyesuaikan perilaku Manager
.
Nama pengelola¶
Secara awalan, Django menambah sebuah Manager
dengan nama objects
pada setiap kelas model Django. Bagaimanapun, jika anda ingin menggunakan objects
sebagai sebuah nama bidang, atau jika anda ingin menggunakan sebuah nama selain dari objects
untuk Manager
, anda dapat menamai kembali itu pada berdasarkan per-model. Untuk menamai kembali Manager
untuk kelas diberikan, tentukan sebuah atribut kelas dari jenis models.Manager()
pada model itu. Sebagai contoh:
from django.db import models
class Person(models.Model):
#...
people = models.Manager()
Menggunakan model contoh ini, Person.objects
akanmembangkitkan sebuah pengecualian AttributeError
, tetapi Person.people.all()
akan menyediakan daftar dari semua obyek Person
.
Pengelolaan penyesuaian¶
Anda dapat menggunakan sebuah penyesuaian Manager
dalam model tertentu dengan memperpanjang kelas Manager
dasar dan menginstansiasi penyesuaian Manager
anda dalam model anda.
Ada dua alasan anda mungkin ingin menyesuaikan sebuah Manager
: untuk menambah metode Manager
tambahan, dan/atau merubah QuerySet
awal kembalian Manager
.
Menambahkan metode pengelolaan tambahan¶
Menambahkan metode Manager
tambahan adalah cara disukai untuk menambah fungsionalitas "table-level" pada model anda. (Untuk fungsionalitas "row-level" -- yaitu yang bertindak pada sebuah instance tunggal dari sebuah obyek model -- gunakan Model methods, bukan penyesuaian metode Manager
.)
Sebagai contoh,``Manager`` penyesuaian ini menambahkan sebuah metode with_counts()
:
from django.db import models
from django.db.models.functions import Coalesce
class PollManager(models.Manager):
def with_counts(self):
return self.annotate(
num_responses=Coalesce(models.Count("response"), 0)
)
class OpinionPoll(models.Model):
question = models.CharField(max_length=200)
objects = PollManager()
class Response(models.Model):
poll = models.ForeignKey(OpinionPoll, on_delete=models.CASCADE)
# ...
With this example, you'd use OpinionPoll.objects.with_counts()
to get a
QuerySet
of OpinionPoll
objects with the extra num_responses
attribute attached.
Sebuah metode Manager
penyesuaian dapat mengembalikan apapun anda inginkan. Itu tidak harus mengembalikan sebuah QuerySet
.
Another thing to note is that Manager
methods can access self.model
to
get the model class to which they're attached.
Merubah QuerySet
awal pengelolaan¶
Dasar Manager
QuerySet
mengembalikan semua obyek-obyek di sistem. Sebagai contoh, menggunakan model ini:
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
...pernyataan Book.objects.all()
akan mengembalikan semua buku-buku di basisdata.
Anda dapat menimpa QuerySet
dasar Manager
dengan menimpa metode Manager.get_queryset()
. get_queryset()
harus mengembalikan sebuah QuerySet
dengan sifat-sifat anda butuhkan.
Sebagai contoh, model berikut mempunyai dua Manager
-- satu yang mengembalikan semua obyek, dan satu yang mengembalikan hanya buku-buku oleh Roald Dahl:
# First, define the Manager subclass.
class DahlBookManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(author='Roald Dahl')
# Then hook it into the Book model explicitly.
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
objects = models.Manager() # The default manager.
dahl_objects = DahlBookManager() # The Dahl-specific manager.
Dengan model contoh ini, Book.objects.all()
akan mengembalikan semua buku-buku di basisdata, tetapi Book.dahl_objects.all()
akan hanya mengembalikan satu yang ditulis oleh Roald Dahl.
Because get_queryset()
returns a QuerySet
object, you can use
filter()
, exclude()
and all the other QuerySet
methods on it. So
these statements are all legal:
Book.dahl_objects.all()
Book.dahl_objects.filter(title='Matilda')
Book.dahl_objects.count()
This example also pointed out another interesting technique: using multiple
managers on the same model. You can attach as many Manager()
instances to
a model as you'd like. This is a non-repetitive way to define common "filters"
for your models.
Sebagai contoh:
class AuthorManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(role='A')
class EditorManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(role='E')
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
role = models.CharField(max_length=1, choices=[('A', _('Author')), ('E', _('Editor'))])
people = models.Manager()
authors = AuthorManager()
editors = EditorManager()
Contoh ini mengizinkan anda meminta Person.authors.all()`, Person.editors.all()
, dan Person.people.all()
, menghasilkan hasil dapat diramalkan.
Pengelola awal¶
-
Model.
_default_manager
¶
Jika anda menggunakan obyek Manager
penyesuaian, ambil catatan bahwa Manager
Django pertama hadapi (dalam urutan dimana mereka ditentukan dalam model) mempunyai sebuah keadaan khusus. Django menafsirkan Manager
pertama ditentukan dalam sebuah kelas sebagai Manager
"default", dan beberapa bagian dari Django (termasuk dumpdata
) akan menggunakan yang Manager
khusus untuk model itu. Sebagai sebuah hasil, itu adalah ide bagus untuk hati-hati dalam pilihan anda dari pengelola awalan untuk menghindari keadan dimana menimpa hasil get_queryset()
dalam sebuah ketidakmampuan mengambil obyek-obyek anda sukai bekerja dengannya.
Anda dapat menentukan sebuah penyesuaian pengelolaan awalan menggunakan Meta.default_manager_name
.
Jika anda sedang menulis beberapa kode yang harus menangani sebuah model tidak dikenal, sebagai contoh, dalam sebuah aplikasi pihak-ketiga yang menerapkan sebuah tampilan umum, gunakan pengelola ini (atau _base_manager
) daripada beranggapan model mempunyai sebuah pengelola objects
.
Pengelolaan dasar¶
-
Model.
_base_manager
¶
Jangan menyaring hasil apapun dalam jenis ini dari pengelola subkelas¶
Pengelola ini digunakan untuk mengakses obyek yang terkait pada dari beberapa model lain. Dalam keadaan tersebut, Django harus dapat melihat semua obyek untuk model itu sedang diambil, sehingga apapun yang mengacu dapat diambil.
Therefore, you should not override get_queryset()
to filter out any rows.
If you do so, Django will return incomplete results.
Memanggil metode QuerySet
penyesuaian dari pengelola¶
Selagi kebanyakan metode dari QuerySet
standar dapat diakses langsung dari Manager
, ini hanya kasus untuk metode tambahan ditentukan pada sebuah penyesuaian QuerySet
jika anda juga menerapkan mereka pada Manager
:
class PersonQuerySet(models.QuerySet):
def authors(self):
return self.filter(role='A')
def editors(self):
return self.filter(role='E')
class PersonManager(models.Manager):
def get_queryset(self):
return PersonQuerySet(self.model, using=self._db)
def authors(self):
return self.get_queryset().authors()
def editors(self):
return self.get_queryset().editors()
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
role = models.CharField(max_length=1, choices=[('A', _('Author')), ('E', _('Editor'))])
people = PersonManager()
Contoh ini mengizinkan anda memanggil kedua authors()
dan editors()
secara langsung dari pengelola Person.people
.
Membuat pengelola dengan cara QuerySet
¶
Sebagai pengganti dari pendekatan diatas yang membutuhkan metode penggandaan pada kedua QuerySet
dan Manager
, QuerySet.as_manager()
dapat digunakan untuk membuat sebuah instance dari Manager
dengan salinan dari sebuah metode QuerySet
penyesuaian:
class Person(models.Model):
...
people = PersonQuerySet.as_manager()
Instance Manager
dibuat oleh QuerySet.as_manager()
akan secara virtual mirip pada PersonManager
dari contoh sebelumnya.
Tidak setiap metode QuerySet
masuk akal pada tingkat Manager
; sebagai contoh kami sengaja mencegah metode QuerySet.delete()
dari menjadi disalin ke atas kelas Manager
.
Cara disalin berdasarkan aturan berikut:
- Cara umum disalin secara awal.
- Metode pribadi (mulai dengan sebuah garis bawah) tidak disalin secara awalan.
- Metode dengan atribut
queryset_only
disetel menjadiFalse
adalah selalu disalin. - Metode dengan atribut
queryset_only
disetel menjadiTrue
adalah tidak pernah disalin.
Sebagai contoh:
class CustomQuerySet(models.QuerySet):
# Available on both Manager and QuerySet.
def public_method(self):
return
# Available only on QuerySet.
def _private_method(self):
return
# Available only on QuerySet.
def opted_out_public_method(self):
return
opted_out_public_method.queryset_only = True
# Available on both Manager and QuerySet.
def _opted_in_private_method(self):
return
_opted_in_private_method.queryset_only = False
from_queryset()
¶
-
classmethod
from_queryset
(queryset_class)¶
Untuk penggunaan lanjutan anda mungkin ingin kedua penyesuaian Manager
dan penyesuaian QuerySet
. Anda dapat melakukan itu dengan memanggil Manager.from_queryset()
yang mengembalikan sebuah subkelas dari dasar Manager
anda dengan salinan dari metode QuerySet
penyesuaian:
class CustomManager(models.Manager):
def manager_only_method(self):
return
class CustomQuerySet(models.QuerySet):
def manager_and_queryset_method(self):
return
class MyModel(models.Model):
objects = CustomManager.from_queryset(CustomQuerySet)()
Anda mungkin juga menyimpan kelas dibangkitkan kedalam sebuah variabel:
MyManager = CustomManager.from_queryset(CustomQuerySet)
class MyModel(models.Model):
objects = MyManager()
Pengelolaan penyesuaian dan warisan model¶
Ini adalah bagaimana Django menangani pengelolaan penyesuaian dan model inheritance:
- Pengelola dari kelas-kelas dasar selalu diwarisi oleh anak kelas, menggunakan urutan resolusi nama biasa Python (nama pada kelas anan menimpa semua lainnya; kemudian datang nama pada kelas induk pertama, dan seterusnya).
- Jika tidak ada pengelola dinyatakan pada model dan/atau induknya, Django secara otomatis membuat pengelola
objects
. - Pengelola awalan pada sebuah kelas adalah antara satu dipilih dengan
Meta.default_manager_name
, atau pengelola pertama dinyatakan pada model, atau pengelola awalan dari model induk pertama.
Aturan-aturan ini menyediakan keluwesan yang dibutuhkan jika anda ingin memasang sebuah kumpulan dari penyesuaian pengelola pada sekelompok model, melalui sebuah kelas dasar, tetapi masih menyesuaikan pengelola awalan. Sebagai contoh, misalkan anda mempunyai kelas dasar ini:
class AbstractBase(models.Model):
# ...
objects = CustomManager()
class Meta:
abstract = True
Jika anda menggunakan ini langsung di sebuah subkelas, objects
akan berupa pengelola awalan jika anda menyatakan tidak ada pengelola di kelas dasar:
class ChildA(AbstractBase):
# ...
# This class has CustomManager as the default manager.
pass
Jika anda ingin mewarisi dari AbstractBase
, tetapi menyediakan pengelola awalan berbeda, anda dapat menyediakan pengelola awalan pada kelas anak:
class ChildB(AbstractBase):
# ...
# An explicit default manager.
default_manager = OtherManager()
Here, default_manager
is the default. The objects
manager is
still available, since it's inherited, but isn't used as the default.
Akhirnya untuk contoh ini, misalkan anda ingin menambah pengelola tambahan pada kelas anak, tetapi masih menggunakan awalan dari AbstractBase
. Anda tidak dapat menambah pengelola baru langsung dalam kelas anak, seperti itu akan menimpa awalan dan anda akan juga jelas menyertakan semua pengelola dari kelas dasar abstrak. Pemecahannya adalah menaruh pengelola tambahan dalam kelas dasar lain dan memperkenalkan itu kedalam hirarki warisan setelah awalan:
class ExtraManager(models.Model):
extra_manager = OtherManager()
class Meta:
abstract = True
class ChildC(AbstractBase, ExtraManager):
# ...
# Default manager is CustomManager, but OtherManager is
# also available via the "extra_manager" attribute.
pass
Catat bahwa selagi anda dapat menentukan pengelolaan penyesuaian pada model abstrak, anda tidak dapat meminta metode apapun menggunakan model abstrak. Yaitu:
ClassA.objects.do_something()
legal, tetapi:
AbstractBase.objects.do_something()
akan memunculkan sebuah pengecualian. Ini karena pengelola bermaksud untuk mengenkapsulasi logika untuk mengelola kumpulan dari obyek. Sejak anda tidak dapat mempunyai sebuah kumpulan dari obyek-obyek abstrak, itu tidak masuk akal untuk mengelola mereka. Jika anda mempunyai fungsionalitas yang berlaku pada model abstrak, anda harus menaruh fungsionalitas itu dalam sebuah staticmethod
atau classmethod
pada model abstrak.
Perhatian penerapan¶
Fitur-fitur apapun anda tambahkan ke Manager
penyesuaian anda, itu harus mungkin untuk membuat salinan dangkal dari sebuah instance Manager
; yaitu, kode berikut harus bekerja:
>>> import copy
>>> manager = MyManager()
>>> my_copy = copy.copy(manager)
Django membuat salinan dangkal dari obyek-obyek pengelola selama permintaan tertentu; jika Manager anda tidak dapat disalin, permintaan itu akan gagal.
Ini tidak akan menjadi sebuah masalah untuk kebanyakan pengelola penyesuaian. Jika anda hanya menambahkan metode sederhana ke Manager
anda, itu tidak mungkin bahwa anda akan secara tidak sengaja membuat instance-instance dari tidak dapat disalin Manager
anda. Bagaimanapun, jika anda menimpa __getattr__
atau beberapa metode pribadi lain dari obyek Manager
anda yang mengendalikan keadaan obyek, anda harus memastikan bahwa anda tidak mempengaruhi kemampuan dari Manager
anda untuk disalin.