# dokumentasi Django 2.2.9.dev20191202104323

# 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`.)

Sebuah metode `Manager` penyesuaian dapat mengembalikan apapun anda inginkan. Itu tidak harus mengembalikan sebuah `QuerySet`.

Sebagai contoh, `Manager` penyesuaian ini menawarkan sebuah metode `with_counts()`, yang mengembalikan sebuah daftar dari semua obyek `OpinionPoll`, setiap dengan sebuah atribut `num_responses` tambahan yaitu hasil dari sebuah pengumpulan permintaan:

    from django.db import models

    class PollManager(models.Manager):
        def with_counts(self):
            from django.db import connection
            with connection.cursor() as cursor:
                cursor.execute("""
                    SELECT p.id, p.question, p.poll_date, COUNT(*)
                    FROM polls_opinionpoll p, polls_response r
                    WHERE p.id = r.poll_id
                    GROUP BY p.id, p.question, p.poll_date
                    ORDER BY p.poll_date DESC""")
                result_list = []
                for row in cursor.fetchall():
                    p = self.model(id=row[0], question=row[1], poll_date=row[2])
                    p.num_responses = row[3]
                    result_list.append(p)
            return result_list

    class OpinionPoll(models.Model):
        question = models.CharField(max_length=200)
        poll_date = models.DateField()
        objects = PollManager()

    class Response(models.Model):
        poll = models.ForeignKey(OpinionPoll, on_delete=models.CASCADE)
        person_name = models.CharField(max_length=50)
        response = models.TextField()

Dengan contoh ini, anda akan menggunakan `OpinionPoll.objects.with_counts()` untuk mengembalikan daftar itu dari obyek `OpinionPoll` dengan atribut `num_responses`.

Hal lain untuk dicatat tentang contoh ini adalah bahwa metode `Manager` dapat mengakses `self.model` untuk mendapatkan kelas model dimana mereka dilampirkan.

### 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.

Tentu saja, karena `get_queryset()` mengembalikan sebuah obyek `QuerySet`, anda dapat menggunakan `filter()`, `exclude()` dan semua dari metode `QuerySet` lain pada itu. Jadi pernyataan ini adalah semua sah:

    Book.dahl_objects.all()
    Book.dahl_objects.filter(title='Matilda')
    Book.dahl_objects.count()

Contoh ini juga menunjuk teknik menarik lainnya: menggunakan banyak pengelola pada model sama. Anda dapat melampirkan sebanyak instance `Manager()` pada sebuah model sesuka anda. Ini adalah cara mudah untuk menentukan "filters" umum untuk model anda.

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`

#### Menggunakan pengelola untuk akses obyek terkait

Secara awalan, Django menggunakan sebuah instance dari kelas pengelola `Model._base_manager` ketika mengakses obyek terkait (yaitu `choice.question`), bukan `_default_manager` pada obyek terkait. Ini karena Django butuh dapat mengambil obyek terkait, bahkan jika itu akan sebaliknya disaring (dan karenanya tidak dapat diakses) oleh pengelola awalan.

Jika kelas pengelola dasar biasa (`django.db.models.Manager`) tidak sesuai untuk keadaan anda, anda dapat memberitahu Django kelas mana digunakan oleh pengaturan `Meta.base_manager_name`.

Base managers aren't used when querying on related models. For example, if the `Question` model from the tutorial had a `deleted` field and a base manager that filters out instances with `deleted=True`, a queryset like `Choice.objects.filter(question__name__startswith='What')` would include choices related to deleted questions.

#### 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.

Jika anda menimpa metode `get_queryset()` dan menyaring setiap baris, Django akan mengembalikan hasil salah. Jangan lakukan itu, Sebuah pengelola yang menyaring hasil dalam `get_queryset()` tidak sesuai untuk digunakan sebagai pengelola dasar.

### 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 menjadi `False` adalah selalu disalin.
- Metode dengan atribut `queryset_only` disetel menjadi `True` 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 BaseManager(models.Manager):
        def manager_only_method(self):
            return

    class CustomQuerySet(models.QuerySet):
        def manager_and_queryset_method(self):
            return

    class MyModel(models.Model):
        objects = BaseManager.from_queryset(CustomQuerySet)()

Anda mungkin juga menyimpan kelas dibangkitkan kedalam sebuah variabel:

    CustomManager = BaseManager.from_queryset(CustomQuerySet)

    class MyModel(models.Model):
        objects = CustomManager()

### Pengelolaan penyesuaian dan warisan model

Ini adalah bagaimana Django menangani pengelolaan penyesuaian dan model inheritance:

1. 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).
2. Jika tidak ada pengelola dinyatakan pada model dan/atau induknya, Django secara otomatis membuat pengelola `objects`.
3. 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()

Disini, `default_manager` adalah awalan. Pengelola `objects` masih tersedia, sejak itu diwarisi. Itu hanya tidak digunakan sebagai awalan.

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.