# Dokumentasi Django 5.2.8

# Mengkostumisasi autentikasi di Django

Autentikasi yang telah disediakan Django sudah cukup baik untuk kasus-kasus pada umumnya, tetapi Anda mungkin memiliki kebutuhan yang tidak dipenuhi oleh fitur bawaan. Mengkostumisasi otentikasi pada proyek-proyek anda membutuhkan pengertian atas bagian-bagian tersedia yang dapat diturunkan atau diubah. Dokumen ini menyediakan detil tentang bagaimana sitem otentikasi dapat dikostumisasi.

Authentication backends menyediakan sebuah sistem yang dapat diperpanjang untuk ketika nama pengguna dan sandi disimpan dengan model pengguna butuh untuk diotentifikasi terhadap layanan berbeda dari awalan Django.

Anda dapat memberikan model anda perizinan custom permissions yang dapat diperiksa melalui sistem otorisasi Django.

Anda dapat extend awalan model `User`, atau substitute sepenuhnya model disesuaikan.

## Sumber pembuktian keaslian lain

Mungkin ada kali anda harus butuh mengait ke dalam sumber pembuktian keaslian lain -- yaitu, sumber lain dari nama pengguna dan sandi atau metode pembuktian keaslian.

Sebagai contoh, perusahaan anda mungkin sudah mempunyai pengaturan LDAP yang menyimpan nama pengguna dan sandi untuk setiap karyawan. Itu akan menjadi cekcok untuk kedua administrator jaringan dan pengguna nya sendiri jika pengguna mempunyai akun terpisah di LDAP dan aplikasi berbasis-Django.

Jadi, untuk menangani keadaan seperti ini, sistem pembuktian keaslian Django membiarkan anda memasang sumber pembuktian keaslian lain. Anda dapat menimpa skema berbasis-basisdata awal Django, atau anda dapat menggunakan sistem awal untuk dipasangkan dengan sistem lain.

Lihat authentication backend reference untuk informasi pada backend otentifikasi yang disertakan dengan Django.

### Menentukan backend pembuktian keaslian

Behind the scenes, Django maintains a list of "authentication backends" that it checks for authentication. When somebody calls `django.contrib.auth.authenticate()` -- as described in How to log a user in -- Django tries authenticating across all of its authentication backends. If the first authentication method fails, Django tries the second one, and so on, until all backends have been attempted.

Daftar backend pembuktian keaslian untuk digunakan ditentukan dalam pengaturan `AUTHENTICATION_BACKENDS`. Ini seharusnya daftar nama jalur Python yang menunjuk ke kelas Python yang mengetahui bagaimana membuktikan keaslian. Kelas ini dapat berada dimanapun di jalur Python anda.

Secara awal, `AUTHENTICATION_BACKENDS` disetel ke:

    ["django.contrib.auth.backends.ModelBackend"]

Itulah backend autentikasi dasar yang memeriksa basis data pengguna Django dan meminta izin bawaan. Itu tidak memberikan perlindungan terhadap serangan brute force melalui mekanisme pembatasan laju apa pun. Anda dapat menerapkan mekanisme pembatasan kecepatan anda sendiri di backend autentikasi khusus, atau menggunakan mekanisme yang disediakan oleh sebagian besar server web.

Urutan masalah `AUTHENTICATION_BACKENDS`, jadi jika nama pengguna dan sandi sama adalah sah di banyak backend, Django akan menghentikan pengolahan pada pertama yang positif cocok.

Jika backend memunculkan pengecualian `PermissionDenied`, pembuktian keaslian akan segera gagal. Django tidak akan memeriksa backend yang mengikuti.

Catatan

Setelah seorang pengguna mengotentikasi, Django menyimpan backend mana yang digunakan untuk mengotentikasi pengguna dalam sesi pengguna, dan menggunakan kembali backend yang sama selama sesi itu kapan pun akses ke pengguna yang diautentikasi saat ini diperlukan. Ini secara efektif berarti bahwa sumber autentikasi di-cache per sesi, jadi jika anda mengubah `AUTHENTICATION_BACKENDS`, Anda harus menghapus data sesi jika anda perlu memaksa pengguna mengautentikasi ulang menggunakan metode yang berbeda. Cara sederhana untuk melakukannya adalah dengan mengeksekusi `Session.objects.all().delete()`.

### Menulis backend pembuktian keaslian

Sebuah backend autentifikasi adalah sebuah kelas yang menerapkan dua metode wajib: `get_user(user_id)` dan `authenticate(request, **credentials)`, dan juga kumpulan dari pilihan perizinan terhubung authorization methods.

Metode `get_user` mengambil `user_id` -- yang bisa berupa nama pengguna, ID basis data, atau apa pun, tetapi harus menjadi kunci utama objek pengguna Anda -- dan mengembalikan objek pengguna atau ``None` `.

Metode `authenticate` mengambil sebuah argumen `request` dan surat pengenal sebagai argumen kata kunci. Sebagian besar waktu, akan terlihat seperti ini

    from django.contrib.auth.backends import BaseBackend

    class MyBackend(BaseBackend):
        def authenticate(self, request, username=None, password=None):
            # Check the username/password and return a user.
            ...

Tetapi itu dapat juga membuktikan keaslian sebuah token, seperti begitu:

    from django.contrib.auth.backends import BaseBackend

    class MyBackend(BaseBackend):
        def authenticate(self, request, token=None):
            # Check the token and return a user.
            ...

Salah satu cara, `authenticate()` harus memeriksa mandat yang dia dapatkan, dan dia harus mengembalikan obyek user yang cocok dengan mandat, jika mandat sah. Jika mereka tidak sah, dia harus mengembalikan `None`.

`request` adalah sebuah `HttpRequest` dan mungkin berupa `None` jika itu tidak disediakan pada `authenticate()` (yang melewatkan itu ke backend).

The Django admin is tightly coupled to the Django User object. For example, for a user to access the admin, `User.is_staff` and `User.is_active` must be `True` (see `AdminSite.has_permission()` for details).

The best way to deal with this is to create a Django `User` object for each user that exists for your backend (e.g., in your LDAP directory, your external SQL database, etc.). You can either write a script to do this in advance, or your `authenticate` method can do it the first time a user logs in.

Here's an example backend that authenticates against a username and password variable defined in your `settings.py` file and creates a Django `User` object the first time a user authenticates. In this example, the created Django `User` object is a superuser who will have full access to the admin:

    from django.conf import settings
    from django.contrib.auth.backends import BaseBackend
    from django.contrib.auth.hashers import check_password
    from django.contrib.auth.models import User

    class SettingsBackend(BaseBackend):
        """
        Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.

        Use the login name and a hash of the password. For example:

        ADMIN_LOGIN = 'admin'
        ADMIN_PASSWORD = 'pbkdf2_sha256$30000$Vo0VlMnkR4Bk$qEvtdyZRWTcOsCnI/oQ7fVOu1XAURIZYoOZ3iq8Dr4M='
        """

        def authenticate(self, request, username=None, password=None):
            login_valid = settings.ADMIN_LOGIN == username
            pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
            if login_valid and pwd_valid:
                try:
                    user = User.objects.get(username=username)
                except User.DoesNotExist:
                    # Create a new user. There's no need to set a password
                    # because only the password from settings.py is checked.
                    user = User(username=username)  # is_active defaults to True.
                    user.is_staff = True
                    user.is_superuser = True
                    user.save()
                return user
            return None

        def get_user(self, user_id):
            try:
                return User.objects.get(pk=user_id)
            except User.DoesNotExist:
                return None

### Menangani otorisasi dalam backend penyesuaian

Penyesuaian backend sah dapat menyediakan perizinan mereka sendiri.

The user model and its manager will delegate permission lookup functions (`get_user_permissions()`, `get_group_permissions()`, `get_all_permissions()`, `has_perm()`, `has_module_perms()`, and `with_perm()`) to any authentication backend that implements these functions.

Perizinan diberikan ke pengguna akan menjadi duperset dari semua perizinan dikembalikan oleh semua backend. Yaitu, Django menghadiahkan sebuah perizinan kepada pengguna bahwa tiap satu hadiah backend.

If a backend raises a `PermissionDenied` exception in `has_perm()` or `has_module_perms()`, the authorization will immediately fail and Django won't check the backends that follow.

Sebuah backend dapat menerapkan perizinan untuk admin sakti seperti ini:

    from django.contrib.auth.backends import BaseBackend

    class MagicAdminBackend(BaseBackend):
        def has_perm(self, user_obj, perm, obj=None):
            return user_obj.username == settings.ADMIN_LOGIN

Ini memberikan perizinan penuh kepada pengguna yang diberikan akses di contoh diatas. Perhatikan bahwa di penambahan ke argumen sama diberikan ke fungsi `django.contrib.auth.models.User` terkait, fungsi pembuktian keaslian backend semua mengambil obyek pengguna, yang mungkin menjadi pengguna anonim, sebagai sebuah argumen.

Penerapan otorisasi penuh dapat ditemukan di kelas `ModelBackend` di django/contrib/auth/backends.py, yang merupakan backend awalan dan sering menanyakan tabel `auth_permission`.

#### Otorisasi untuk pengguna anonim

Sebuah pengguna anonim adalah satu yang tidak dibuktikan keaslian yaitu mereka menyediakan rincian pembuktian keaslian yang tidak sah. Bagaimanapun, itu tidak dibutuhkan berarti mereka tidak diotorisasikan melakukan apapun. Pada kebanyakan tingkatan dasar, kebanyakan situs jaringan mengotorisasi pengguna anonim untuk menjelajahi kebanyakan situs, dan banyak mengizinkan pengguna memasang komentar dll.

Kerangka izin Django tidak memiliki tempat untuk menyimpan izin untuk pengguna anonim. Namun, objek pengguna diteruskan ke backend autentikasi dapat berupa objek `django.contrib.auth.models.AnonymousUser`, mengizinkan backend untuk menentukan perilaku otorisasi penyesuaian untuk pengguna anonim. Ini sangat berguna bagi pembuat aplikasi yang dapat digunakan kembali, yang dapat mendelegasikan semua pertanyaan otorisasi ke backend autentikasi, daripada memerlukan setelan, misalnya, untuk mengontrol akses anonim.

#### Otorisasi untuk pengguna tidak aktif

Seorang pengguna tidak aktif adalah satu yang mempunyai bidang `is_active` nya disetel menjadi `False`. Backend otentifikasi `ModelBackend` dan `RemoteUserBackend` melarang pengguna ini dari otentifikasi. Jika model pengguna penyesuaian tidak mempunyai bidang `is_active`, semua pengguna akan diizinkan untuk otentifikasi.

Anda dapat menggunakan `AllowAllUsersModelBackend` atau `AllowAllUsersRemoteUserBackend` jika anda ingin mengizinkan pengguna tidak aktif untuk diotentifikasi.

Dukungan untuk pengguna anonim di sistem perizinan mengizinkan untuk sebuah skenaria dimana pengguna anonim mempunyai perizinan untuk melakukan sesuatu selama pengguna dibuktikan keaslian tidak aktif tidak.

Jangan lupa untuk mencoba untuk atribut `is_active` dari pengguna di cara perizinan backend anda sendiri.

#### Penanganan perizinan obyek

Kerangka perizinan Django mempunyai sebuahyayasan untuk perizinan obyek, meskipun tidak ada penerapa untuknya didalam inti. Hal ini berarti bahwa memeriksa untuk perizinan obyek akan selalu mengembalikan `False` atau daftar kosong (tergantung pada penampilan pemeriksaan). Sebuah backend pembuktian keaslian akan menerima parameter katakunci `obj` dan `user_obj` untuk setiap obyek terkait cara otorisasi dan dapat mengembalikan tingkat perizinan obyek sewajarnya.

## Penyesuaian perizinan

Untuk membuat perizinan penyesuaian untuk obyek model yang diberikan, gunakan `permissions` model Meta attribute.

Contoh ini model `Task` membuat dua penyesuaian perizinan, yaitu, tindakan pengguna dapat atau tidak dapat dengan contoh-contoh `Task`, khusus ke aplikasi anda:

    class Task(models.Model):
        ...

        class Meta:
            permissions = [
                ("change_task_status", "Can change the status of tasks"),
                ("close_task", "Can remove a task by setting its status as closed"),
            ]

Satu-satunya hal yang dilakukan adalah membuat izin tambahan tersebut saat anda menjalankan `manage.py migrate` (fungsi yang membuat izin terhubung ke sinyal `post_migrate`). Kode anda bertugas memeriksa nilai izin ini saat pengguna mencoba mengakses kegunaan yang disediakan oleh aplikasi (mengubah status tugas atau menutup tugas.) Melanjutkan contoh di atas, berikut ini memeriksa apakah pengguna dapat menutup tugas:

    user.has_perm("app.close_task")

## Memperpanjang model `User` yang ada

Terdapat dua jalan untuk memperpanjang model `User` awal tanpa mengganti model milik anda. Jika perubahan anda butuhkan murni kebiasaan, dan tidak membutuhkan perubahan apapun ke apa ang disimpan di basisdata, anda dapat membuat proxy model berdasarkan pada `User`. Ini mengizinkan fitur apapun ditawarkan oleh model proxy termasuk pemesanan awal, pengelola penyesuaian, atau cara model penyesuaian.

Jika anda berharap menyimpan informasi terkait ke `User`, anda dapat menggunakan `OneToOneField` pada sebuah model mengandung bidang untuk informasi tambahan. Ini model satu-ke-satu selalu memanggil model profil, karena dia akan menyimpan informasi terkait bukan-asli tentang pengguna situs. Sebagai contoh anda mungkin membuat sebuah model Employee:

    from django.contrib.auth.models import User

    class Employee(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        department = models.CharField(max_length=100)

Asumsikan ada Karyawan Fred Smith yang memiliki model User dan Employee, anda dapat mengakses informasi terkait menggunakan konvensi model terkait standar Django:

    >>> u = User.objects.get(username="fsmith")
    >>> freds_department = u.employee.department

Untuk menambahkan profil bidang model ke halaman pengguna dalam admin, tentukan sebuah class:~django.contrib.admin.InlineModelAdmin (untuk contoh ini, kami akan menggunakan `StackedInline`) di `admin.py` aplikasi anda dan menambahkannya ke kelas `UserAdmin` yang terdaftar dengan kelas `User`:

    from django.contrib import admin
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    from django.contrib.auth.models import User

    from my_user_profile_app.models import Employee

    # Define an inline admin descriptor for Employee model
    # which acts a bit like a singleton
    class EmployeeInline(admin.StackedInline):
        model = Employee
        can_delete = False
        verbose_name_plural = "employee"

    # Define a new User admin
    class UserAdmin(BaseUserAdmin):
        inlines = [EmployeeInline]

    # Re-register UserAdmin
    admin.site.unregister(User)
    admin.site.register(User, UserAdmin)

Model profil ini tidak khusus dengan cara apapun - mereka hanya model Django yang terjadi untuk memiliki tautan one-to-one dengan model user. Dengan demikian, mereka tidak dibuat otomatis ketika pengguna dibuat, tetapi `django.db.models.signals.post_save` dapat digunakan untuk membuat atau memperbaharui model sewajarnya.

menggunakan hasil model terkait di tambahan permintaan atau penggabungan untuk mendapatkan data terkait. Tergantung pada kebutuhan anda, penyesuaian model user yang menyertakan bidang terkait mungkin pilihan terbaik anda, bagaimanapun hubungan yang ada pada model user awalan dalam aplikasi proyek anda mungkin membenarkan muatan basisdata lebih.

## Mengganti model `User` penyesuaian

Beberapa macam proyek mungkin mempunyai persyaratan pembuktian keaslian untuk dimana model `User` siap-pakai Django tidak selalu sesuai. Sebagai contoh, pada beberapa situs akan masuk akal menggunakan sebuah alamat surel sebagai token pencirian daripada nama pengguna.

Django mengizinkan anda untuk menimpa model pengguna awalan dengan menyediakan nilai untuk pengaturan `AUTH_USER_MODEL` yang mengacu model penyesuaian:

    AUTH_USER_MODEL = "myapp.MyUser"

Pasangan bertitik ini menjelaskan `label` dari aplikasi Django (yang harus ada di `INSTALLED_APPS` anda), dan nama dari model Django yang ingin anda gunakan sebagai model pengguna.

### Menggunakan model pengguna penyesuaian ketika memulai sebuah proyek

If you're starting a new project, you can set up a custom user model that behaves identically to the default user model by subclassing `AbstractUser`:

    from django.contrib.auth.models import AbstractUser

    class User(AbstractUser):
        pass

Jangan lupa menunjuk `AUTH_USER_MODEL` ke itu. Lakukan ini sebelum membuat perpindahan apapun atau menjalankan `manage.py migrate` untuk pertama kalinya.

Juga, daftar model dalam `admin.py` aplikasi:

    from django.contrib import admin
    from django.contrib.auth.admin import UserAdmin
    from .models import User

    admin.site.register(User, UserAdmin)

### Merubah ke proyek-tengah penyesuaian model user

Changing `AUTH_USER_MODEL` after you've created database tables is possible, but can be complex, since it affects foreign keys and many-to-many relationships, for example.

Perubahan ini tidak dapat diselesaikan secara otomatis dan membutuhkan perbaikan secara manual skema anda, memindahkan data anda dari tabel user lama, dan kemungkinan secara manual memberlakukan kembali beberapa perpindahan. Lihat #25313 untuk ringkasan dari langkah-langkah.

Karena pembatasan dari fitur ketergantungan dinamis Django untuk model-model dapat ditukar, pengacuan model oleh `AUTH_USER_MODEL` harus dibuat di perpindahan pertama dari aplikasinya (biasanya dipanggil `0001_initial`); sebaliknya, anda akan mempunyai masalah ketergantungan.

Sebagai tambahan, anda mungkin berjalan kedalam `CircularDependencyError` ketika menjalankan perpindahan anda sebagai Django tidak akan dapat secara otomatis memutus ketergantungan pada ketergantungan dinamis. Jika anda melihat kesalahan ini, anda harus memutuskan perulangan dengan memindahkan model bergantung pada model user anda kedalam perindahan kedua. (Anda dapat mencoba membuat dua model biasa yang memiliki `ForeignKey` ke setiap lainnya dan melihat bagaimana `makemigrations` mengatasi lingkaran ketergantungan jika anda ingin melihat bagaimana itu biasanya diselesaikan.)

### Aplikasi digunakan kembali `AUTH_USER_MODEL`

Aplikasi dapat digunakan kembali tidak harus menerapkan penyesuaian model user. Sebuah proyek mungkin menggunakan banyak aplikasi, dan dua aplikasi dapat digunakan kembali yang menerapkan penyesuaian model user tidak dapat digunakan bersama-sama. Jika anda butuh menyimpan per informasi pengguna di aplikasi anda, gunakan `ForeignKey` atau `OneToOneField` pada `settings.AUTH_USER_MODEL` seperti yang digambarkan dibawah.

### Mengacu model `User`

Jika anda mengacu `User` secara langsung (sebagai contoh, dengan mengacu ke itu di foreign key), kode anda tidak akan bekerja di proyek dimana pengaturan `AUTH_USER_MODEL` telah berubah ke model user berbeda.

get_user_model()

  Daripada mengacu ke `User` secara langsung, anda harus mengacu modl user menggunakan `django.contrib.auth.get_user_model()`. Metode ini akan mengembalikan model user aktif saat ini -- penyesuaian model user jika satu adalah ditentukan, atau `User` sebaliknya.

  Ketika anda menentukan foreign key atau hubungan many-to-many pada model pengguna, anda harus menentukan model penyesuaian menggunakan pengaturan `AUTH_USER_MODEL`. Sebagai contoh:

      from django.conf import settings
      from django.db import models

      class Article(models.Model):
          author = models.ForeignKey(
              settings.AUTH_USER_MODEL,
              on_delete=models.CASCADE,
          )

  Ketika terhubung ke sinyal yang dikirim oleh model User. anda harus menentukan penyesuaian model menggunakan pengaturan `AUTH_USER_MODEL`. Sebagai contoh:

      from django.conf import settings
      from django.db.models.signals import post_save

      def post_save_receiver(sender, instance, created, **kwargs):
          pass

      post_save.connect(post_save_receiver, sender=settings.AUTH_USER_MODEL)

  Secara umum, itu paling mudah mengacu ke model user dengan pengaturan `AUTH_USER_MODEL` dalam kode yang dijalankan pada waktu impor, bagaimanapun, itu juga memungkinkan memanggil `get_user_model()` selagi Django mengimpor model, jadi anda dapat menggunakan `models.ForeignKey(get_user_model(), ...)`.

  Jika aplikasi anda dicobakan dengan banyak model user, menggunakan `@override_settings(AUTH_USER_MODEL=...)` sebagai contoh, dan anda meng cache hasil dari `get_user_model()` dalam sebuah variabel tingkat-variabel, anda mungkin butuh mendengarkan pada sinyal `setting_changed` untuk membersihkan cache. Sebagai contoh:

      from django.apps import apps
      from django.contrib.auth import get_user_model
      from django.core.signals import setting_changed
      from django.dispatch import receiver

      @receiver(setting_changed)
      def user_model_swapped(*, setting, **kwargs):
          if setting == "AUTH_USER_MODEL":
              apps.clear_cache()
              from myapp import some_module

              some_module.UserModel = get_user_model()

### Menentukan model pengguna penyesuaian

Ketika anda memulai proyek anda dengabn model user penyesuaian, hentikan untuk mempertimbangkan jika ini pilihan tepat untuk proyek anda.

Menyimpan semua informasi terkait pengguna dalam satu model menghilangkan kebutuhan akan permintaan basisdata tambahan atau yang lebih kompleks untuk mengambil model terkait. Di sisi lain, mungkin lebih cocok untuk menyimpan informasi pengguna khusus aplikasi dalam model yang memiliki hubungan dengan model pengguna khusus anda. Itu memungkinkan setiap aplikasi menentukan persyaratan data penggunanya sendiri tanpa berpotensi bertentangan atau melanggar asumsi oleh aplikasi lain. Ini juga berarti bahwa anda akan menjaga model pengguna Anda sesederhana mungkin, fokus pada otentikasi, dan mengikuti persyaratan minimum yang Django harapkan untuk dipenuhi oleh model pengguna penyesuaian.

Jika anda menggunakan backend pembuktian keaslian awal, kemudian model anda harus mempunyai bidang unik tunggal yang dapat digunakan untuk tujuan pencirian. Ini dapat berupa nama pengguna, sebuah alamat surel, atau atribut unik lainnya. Bidang nama pengguna tidak unik diizinkan jika anda menggunakan penyesuaian backend pembuktian keaslian yang dapat mendukungnya.

Cara termudah untuk membangun selalu tunduk penyesuaian model user adalah mewarisi dari `AbstractBaseUser`. `AbstractBaseUser` menyediakan inti penerapan dari model user, termasuk sandi bercampur dan setel kembali sandi token. Anda harus kemudian menyediakan beberapa kunci penerapan rincian:

class models.CustomUser
  USERNAME_FIELD

    Sebuah string yang menjelaskan nama bidang pada model pengguna yang digunakan sebagai pengidentifikasi unik. Ini biasanya berupa nama pengguna, tetapi bisa juga berupa alamat surel, atau pengidentifikasi unik lainnya. Bidang harus unik (mis. memiliki `unique=True` ditetapkan dalam pengertiannya), kecuali jika anda menggunakan backend autentikasi khusus yang dapat mendukung nama pengguna tidak-unik.

    Dalam contoh berikut, bidang `identifier` digunakan sebagai bidang pengenal:

        class MyUser(AbstractBaseUser):
            identifier = models.CharField(max_length=40, unique=True)
            ...
            USERNAME_FIELD = "identifier"

  EMAIL_FIELD

    Sebuah string menggambarkan nama dari bidang surel pada model `User`. Nilai ini dikembalikan oleh `get_email_field_name()`.

  REQUIRED_FIELDS

    Sebuah daftar dari nama bidang yang akan diminta ketika membuat sebuah pengguna melalui perintah pengelolaan `createsuperuser`. Pengguna akan diminta untuk menyediakan nilai untuk setiap bidang ini. Itu harus menyertakan bidang apapun yang `blank` adalah `False` atau tidak menentukan dan mungkin disertakan bidang tambahan anda ingin minta ketika sebuah pengguna dibuat secara interaktif. `REQUIRED_FIELDS` tidak mempunyai efek di bagian lagi dari Django, seperti membuat sebuah pengguna di admin.

    Sebagai contoh, ini ada pengertian sebagian untuk model pengguna yang menentukan dua bidang wajib- tanggal lahir dan tinggi:

        class MyUser(AbstractBaseUser):
            ...
            date_of_birth = models.DateField()
            height = models.FloatField()
            ...
            REQUIRED_FIELDS = ["date_of_birth", "height"]

    Catatan

    `REQUIRED_FIELDS` harus mengandung semua bidang diwajibkan pada model pengguna anda, tetapi tidak mengandung `USERNAME_FIELD` atau `password` ketika bidang ini selalu diminta.

  is_active

    A boolean attribute that indicates whether the user is considered "active". This attribute is provided as an attribute on `AbstractBaseUser` defaulting to `True`. How you choose to implement it will depend on the details of your chosen auth backends. See the documentation of the `is_active attribute on the built-in user model` for details.

  get_full_name()

    Pilihan. Penciri resmi lebih panjang untuk pengguna seperti nama penuh mereka. Jika diterapkan, ini muncul disamping nama pengguna dalam riwayat obyek dalam `django.contrib.admin`.

  get_short_name()

    Pilihan. Pendek, penciri tidak resmi untuk pengguna seperti nama pertama mereka. Jika diterapkan, ini mengganti nama pengguna dalam salam sapa ke pengguna di kepala dari `django.contrib.admin`.

  Mengimpor `AbstractBaseUser`

  `AbstractBaseUser` dan `BaseUserManager` dapat diimpor dari `django.contrib.auth.base_user` sehingga mereka dapat diimpor tanpa menyertakan `django.contrib.auth` di `INSTALLED_APPS`.

Atribut dan cara berikut tersedia pada setiap subkelas dari `AbstractBaseUser`:

class models.AbstractBaseUser
  get_username()

    Mengembalikan nilai dari bidang dicalonkan oleh `USERNAME_FIELD`.

  clean()

    Normalisasikan nama pengguna dengan memanggil `normalize_username()`. Jika anda menimpa cara ini, pastikan memanggil `super()` untuk menahan normalisasi.

  classmethod get_email_field_name()

    Mengembalikan nama dari bidang surel ditentukan oleh atribut `EMAIL_FIELD`. Awalan pada `'email'` jika `EMAIL_FIELD` tidak ditentukan.

  classmethod normalize_username(username)

    Memberlakukan normalisasi Unicode NFKC pada nama pengguna sehingga nampak karakter mirip dengan titik kode Unicode berbeda dianggap mirip.

  is_authenticated

    Atribut hanya-baca yang selalu `True` (sebagai lawan `AnonymousUser.is_authenticated` yang selalu `False`). Ini adalah cara untuk memberitahu jika pengguna telah diotentifikasi. Ini tidak berarti perizinan apapun dan tidak memeriksa jika pengguna adalah aktif atau mempunyai sesi sah. Meskipun secara biasa anda akan memeriksa atribut ini pada `request.user` untuk menemukan apakah itu telah dikumpulkan oleh `AuthenticationMiddleware` (mewakili pengguna masuk saat ini), anda harus mengetahui atribut ini adalah `True` untuk tiap instance `User`.

  is_anonymous

    Atribut hanya-baca yaitu selalu `False`. Ini adalah jalan untuk membedakan obyek `User` and `AnonymousUser`. Umumnya, anda harus memilih menggunakan `is_authenticated` pada atribut ini.

  set_password(raw_password)

    Setel sandi pengguna ke deretan karakter mentah yang diberikan, merawat has sandi. Tidak menyimpan obyek `AbstractBaseUser`.

    When the raw_password is `None`, the password will be set to an unusable password, as if `set_unusable_password()` were used.

  check_password(raw_password)
  acheck_password(raw_password)

    Versi asinkron: `acheck_password()`

    Mengembalikan `True` jika deretan karakter mentah yang diberikan adalah sandi benar untuk pengguna. (Ini merawat hash sandi dalam membuat perbandingan.)

  set_unusable_password()

    Marks the user as having no password set. This isn't the same as having a blank string for a password. `check_password()` for this user will never return `True`. Doesn't save the `AbstractBaseUser` object.

    Anda mungkin butuh ini jika otentifikasi untuk aplikasi anda memakan tempat terhadap sumber luar yang ada seperti pelipat LDAP.

  has_usable_password()

    Returns `False` if `set_unusable_password()` has been called for this user.

  get_session_auth_hash()

    Mengembalikan nilai HMAC dari kolom kata sandi. Digunakan untuk Penghapusan sesi pada perubahan sandi.

  get_session_auth_fallback_hash()

    Menghasilkan HMAC bidang kata sandi menggunakan `SECRET_KEY_FALLBACKS`. Digunakan oleh `get_user()`.

`AbstractUser` subkelas `AbstractBaseUser`:

class models.AbstractUser
  clean()

    Normalisasikan surel dengan memanggil `BaseUserManager.normalize_email()`. Jika anda menimpa cara ini, pastikan memanggil `super()` untuk menahan normalisasi.

### Menulis sebuah pengelola untuk model pengguna penyesuaian

Anda juga harus menentukan pengelola khusus untuk model pengguna Anda. Jika model pengguna Anda mendefinisikan bidang `username`, `email`, `is_staff`, `is_active`, `is_superuser`, `last_login`, dan `date_joined` dengan bidang yang sama sebagai pengguna awalan Django, anda dapat memasang `UserManager` Django; namun, jika model pengguna anda mendefinisikan bidang yang berbeda, anda akan perlu mendefinisikan pengelola penyesuaian yang memperluas `BaseUserManager` menyediakan dua cara tambahan:

class models.CustomUserManager
  create_user(username_field, password=None, **other_fields)

    Sifat dari `create_user()` harus menerima bidang nama pengguna, ditambah semua bidang wajib sebagai argumen. Sebagai contoh, jika model pengguna anda menggunakan `email` sebagai bidang nama pengguna, dan mempunyai `date_of_birth` sebagai bidang wajib, kemudian `create_user` harus ditentukan sebagai:

        def create_user(self, email, date_of_birth, password=None):
            # create user here
            ...

  create_superuser(username_field, password=None, **other_fields)

    Sifat dari `create_superuser()` harus menerima bidang nama pengguna, ditambah semua bidang wajib sebagai argumen. Sebagai contoh, jika model pengguna anda menggunakan `email` sebagai bidang nama pengguna, dan mempunyai `date_of_birth` sebagai bidang wajib, kemudian `create_superuser` harus ditentukan sebagai:

        def create_superuser(self, email, date_of_birth, password=None):
            # create superuser here
            ...

Untuk `ForeignKey` di `USERNAME_FIELD` atau `REQUIRED_FIELDS`, metode ini menerima nilai dari `to_field` (the :attr:` ~django.db.models.Field.primary_key` secara default) dari instance yang ada.

`BaseUserManager` menyediakan cara kegunaan berikut:

class models.BaseUserManager
  classmethod normalize_email(email)

    Menormalkan alamat surel dengan menghuruf kecilkan bagian ranah dari alamat surel.

  get_by_natural_key(username)
  aget_by_natural_key(username)

    Asynchronous version: `aget_by_natural_key()`

    Mengambil instance pengguna menggunakan isi dari bidang dicalonkan oleh `USERNAME_FIELD`.

    Changed in Django 5.2:

    `aget_by_natural_key()` method was added.

### Memperpanjang `User` awal Django

Jika anda sepenuhnya puas dengan model `User` Django, tetapi anda ingin menambahkan beberapa informasi profil tambahan, Anda dapat membuat subkelas `django.contrib.auth.models. AbstractUser` dan tambahkan bidang profil khusus anda, meskipun kami menyarankan model terpisah seperti yang dijelaskan di Menentukan model pengguna penyesuaian. `AbstractUser` menyediakan implementasi penuh dari awalan `User` as an abstract model.

### Penyesuaian pengguna dan formulir otentifikasi siap-pakai

SIap-pakai Django forms dan views membuat pendapat tertentu tentang model user yang mereka bekerja dengannya.

Bentuk berikut cocok dengan subkelas apapun dari `AbstractBaseUser`:

- `AuthenticationForm`: Menggunakan bidang nama pengguna ditentukan oleh `USERNAME_FIELD`.

- `SetPasswordForm`

- `PasswordChangeForm`

- `AdminPasswordChangeForm`

Formulir berikut membuat pendapat tentang model user dan dapat digunakan dengan adanya jika pendapat tersebut dipenuhi:

- `PasswordResetForm`: Beranggapan bahwa model user mempunyai sebuah bidang yang menyimpan alamat surel pengguna dengan nama dikembalikan oleh `get_email_field_name()` (`email` secara awalan) yang dapat digunakan untuk mencirikan pengguna dan bidang boolean bernama `is_active` untuk mencegah penyetelan kembali sandi untuk pengguna tidak aktif.

Akhirnya, formulir berikut diikat pada `User` dan butuh ditulis kembali atau diperpanjang untuk bekerja dengan penyesuaian model user:

- `UserCreationForm`

- `UserChangeForm`

Jika model pengguna penyesuaian anda adalah subkelas dari `AbstractUser`, maka Anda dapat memperluas formulir ini dengan cara ini:

    from django.contrib.auth.forms import UserCreationForm
    from myapp.models import CustomUser

    class CustomUserCreationForm(UserCreationForm):
        class Meta(UserCreationForm.Meta):
            model = CustomUser
            fields = UserCreationForm.Meta.fields + ("custom_field",)

### Penyesuaian pengguna dan `django.contrib.admin`

Jika anda ingin penyesuaian model user anda juga bekerja dengan admin, model user anda harus menentukan beberapa atribut dan metode tambahan. Cara ini mengizinkan admin mengendalikan akses user ke isi admin:

class models.CustomUser

is_staff

  Mengembalikan `True` jika pengguna diizinkan mempunyai akses ke situs admin

is_active

  Mengembalikan `True` jika akun pengguna saat ini aktif.

has_perm(perm, obj=None):

  Mengembalikan `True` jika pengguna mempunyai perizinan nama. Jika `obj` disediakan, perizinan butuh diperiksa terhadap instace obyek tertentu.

has_module_perms(app_label):

  Mengembalikan `True` jika pengguna mempunyai perizinan untuk mengakses model pada aplikasi yang diberikan.

Anda akan juga butuh mendaftarkan model pengguna penyesuaian anda dengan admin. Jika model pengguna penyesuaian anda memperpanjang `django.contrib.auth.models.AbstractUser`, anda dapat menggunakan kelas `django.contrib.auth.admin.UserAdmin` yang ada dari Django. Bagaimanapun, jika model pengguna anda memperpanjang `AbstractBaseUser`, anda akan butuh menentukan kelas `ModelAdmin` penyesuaian. Itu memungkinkan untuk mensubkelaskan awalan `django.contrib.auth.admin.UserAdmin`; bagaimanapun, anda akan butuh menimpa tiap pengertian yang mengacu ke bidang pada `django.contrib.auth.models.AbstractUser` yang tidak pada kelas pengguna penyesuaian anda.

Catatan

Jika anda menggunakan `ModelAdmin` khusus yang merupakan subkelas dari `django.contrib.auth.admin.UserAdmin`, maka anda perlu menambahkan bidang khusus anda ke `fieldsets` (untuk bidang yang akan digunakan dalam mengedit pengguna) dan ke `add_fieldsets` (untuk kolom yang akan digunakan saat membuat pengguna). Misalnya:

    from django.contrib.auth.admin import UserAdmin

    class CustomUserAdmin(UserAdmin):
        ...
        fieldsets = UserAdmin.fieldsets + ((None, {"fields": ["custom_field"]}),)
        add_fieldsets = UserAdmin.add_fieldsets + ((None, {"fields": ["custom_field"]}),)

Lihat a full example untuk rincian lebih.

### Penyesuaian pengguna dan perizinan

Untuk membuatnya lebih mudah untuk menyertakan kerangka kerja perizinan Django kedalam kelas user anda sendiri, Django menyediakan `PermissionsMixin`. Ini adalah model abstrak anda dapat sertakan di susunan tingkat kelas untuk model user anda. memberikan anda semua metode dan bidang basisdata yang diperlukan untuk mendukung model perizinan Django.

`PermissionsMixin` menyediakan cara dan atribut berikut:

class models.PermissionsMixin
  is_superuser

    Boolean. Menunjuk bahwa pengguna ini mempunyai semua perizinan tanpa secara jelas menetapkan mereka.

  get_user_permissions(obj=None)

    Mengembalikan sekumpulan string perizinan yang pengguna miliki secara langsung.

    Jika `obj` dilewatkan, hanya mengembalikan perizinan pengguna untuk objek khusus ini.

  get_group_permissions(obj=None)

    Mengembalikan deretan karakter kumpulan perizinan yang pengguna punyai, melalui kelompok mreka.

    Jika `obj` diloloskan, hanya mengembalikan perizinan kelompok untuk obyek tertentu ini.

  get_all_permissions(obj=None)

    Mengembalikan sekumpulan deretan karakter perizinan yang pengguna punyai, kedua melalui perizinan kelompok dan pengguna.

    Jika `obj` diloloskan. hanya mengembalikan perizinan untuk obyek tertentu ini.

  has_perm(perm, obj=None)

    Mengembalikan `True` jika pengguna memiliki perijinan yang ditentukan, dimana `perm` dalam bentuk `"<app label>.<permission codename>"` (lihat permissions). Jika `User.is_active` dan `is_superuser` keduanya `True`, metode ini selalu mengembalikan `True`.

    Jika `obj` diloloskan, metode ini tidak akan memeriksa untuk sebuah perizinan untuk model, tetapi untuk obyek tertentu ini.

  has_perms(perm_list, obj=None)

    Mengembalikan `True` jika pengguna mempunyai setiap dari perijinan yang ditentukan, dimana setiap perijinan dalam bentuk `"<app label>.<permission codename>"`. Jika `User.is_active` dan `is_superuser` keduanya `True`, metode ini selalu mengembalikan `True`.

    Jika `obj` diloloskan, metode ini tidak akan memeriksa untuk perizinan-perizinan untuk model, tetapi untuk obyek tertentu.

  has_module_perms(package_name)

    Mengembalikan `True` jika pengguna memiliki izin dalam paket yang diberikan (label aplikasi Django). Jika `User.is_active` dan `is_superuser` keduanya `True`, metode ini selalu mengembalikan `True`.

`PermissionsMixin` dan `ModelBackend`

Jika anda tidak menyertakan `PermissionsMixin`, anda harus memastikan anda tidak meminta metode perizinan pada `ModelBackend`. `ModelBackend` menggangap bahwa bidang tertentu itu tersedia di model user anda. Jika model user anda tidak menyediakan bidang tersebut, anda akan menerima kesalahan basisdata ketika anda memeriksa perizinan.

### Penyesuaian pengguna dan model proxy

Satu batasan dari penyesuaian model user adalah bahwa memasang penyesuaian model user akan memutus tiap model proxy memperpanjang `User`. Model proxy harus berdasarkan pada kelas dasar nyata; dengan menentukan penyesuaian model user, anda memindah kemampuan dari Django untuk menciri yang handal kelas dasar.

Jika proyek anda menggunakan model proxy, anda harus salah satu merubah proxy untuk memperpanjang model yser yang digunakan di proyek anda, atau menggabungkan kebiasaan proxy anda kedalam subkelas `User`.

### Sebuah contoh penuh

Berikut adalah contoh aplikasi pengguna khusus yang sesuai dengan admin. Model pengguna ini menggunakan alamat email sebagai nama pengguna, dan memiliki tanggal lahir yang diperlukan; itu tidak memberikan pemeriksaan izin di luar bendera `admin` pada akun pengguna. Model ini akan cocok dengan semua formulir dan tampilan autentikasi bawaan, kecuali untuk formulir pembuatan pengguna. Contoh ini mengilustrasikan bagaimana sebagian besar komponen bekerja sama, namun tidak dimaksudkan untuk disalin langsung ke proyek untuk penggunaan produksi.

Kode ini akan semua tinggal di berkas `models.py` untuk aplikasi otentifikasi penyesuaian:

    from django.db import models
    from django.contrib.auth.models import BaseUserManager, AbstractBaseUser

    class MyUserManager(BaseUserManager):
        def create_user(self, email, date_of_birth, password=None):
            """
            Creates and saves a User with the given email, date of
            birth and password.
            """
            if not email:
                raise ValueError("Users must have an email address")

            user = self.model(
                email=self.normalize_email(email),
                date_of_birth=date_of_birth,
            )

            user.set_password(password)
            user.save(using=self._db)
            return user

        def create_superuser(self, email, date_of_birth, password=None):
            """
            Creates and saves a superuser with the given email, date of
            birth and password.
            """
            user = self.create_user(
                email,
                password=password,
                date_of_birth=date_of_birth,
            )
            user.is_admin = True
            user.save(using=self._db)
            return user

    class MyUser(AbstractBaseUser):
        email = models.EmailField(
            verbose_name="email address",
            max_length=255,
            unique=True,
        )
        date_of_birth = models.DateField()
        is_active = models.BooleanField(default=True)
        is_admin = models.BooleanField(default=False)

        objects = MyUserManager()

        USERNAME_FIELD = "email"
        REQUIRED_FIELDS = ["date_of_birth"]

        def __str__(self):
            return self.email

        def has_perm(self, perm, obj=None):
            "Does the user have a specific permission?"
            # Simplest possible answer: Yes, always
            return True

        def has_module_perms(self, app_label):
            "Does the user have permissions to view the app `app_label`?"
            # Simplest possible answer: Yes, always
            return True

        @property
        def is_staff(self):
            "Is the user a member of staff?"
            # Simplest possible answer: All admins are staff
            return self.is_admin

Kemudian, untuk mendaftar model pengguna penyesuaian dengan admin Django, kode berikut akan diwajibkan di berkas `admin.py` aplikasi:

    from django import forms
    from django.contrib import admin
    from django.contrib.auth.models import Group
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    from django.contrib.auth.forms import ReadOnlyPasswordHashField
    from django.core.exceptions import ValidationError

    from customauth.models import MyUser

    class UserCreationForm(forms.ModelForm):
        """A form for creating new users. Includes all the required
        fields, plus a repeated password."""

        password1 = forms.CharField(label="Password", widget=forms.PasswordInput)
        password2 = forms.CharField(
            label="Password confirmation", widget=forms.PasswordInput
        )

        class Meta:
            model = MyUser
            fields = ["email", "date_of_birth"]

        def clean_password2(self):
            # Check that the two password entries match
            password1 = self.cleaned_data.get("password1")
            password2 = self.cleaned_data.get("password2")
            if password1 and password2 and password1 != password2:
                raise ValidationError("Passwords don't match")
            return password2

        def save(self, commit=True):
            # Save the provided password in hashed format
            user = super().save(commit=False)
            user.set_password(self.cleaned_data["password1"])
            if commit:
                user.save()
            return user

    class UserChangeForm(forms.ModelForm):
        """A form for updating users. Includes all the fields on
        the user, but replaces the password field with admin's
        disabled password hash display field.
        """

        password = ReadOnlyPasswordHashField()

        class Meta:
            model = MyUser
            fields = ["email", "password", "date_of_birth", "is_active", "is_admin"]

    class UserAdmin(BaseUserAdmin):
        # The forms to add and change user instances
        form = UserChangeForm
        add_form = UserCreationForm

        # The fields to be used in displaying the User model.
        # These override the definitions on the base UserAdmin
        # that reference specific fields on auth.User.
        list_display = ["email", "date_of_birth", "is_admin"]
        list_filter = ["is_admin"]
        fieldsets = [
            (None, {"fields": ["email", "password"]}),
            ("Personal info", {"fields": ["date_of_birth"]}),
            ("Permissions", {"fields": ["is_admin"]}),
        ]
        # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
        # overrides get_fieldsets to use this attribute when creating a user.
        add_fieldsets = [
            (
                None,
                {
                    "classes": ["wide"],
                    "fields": ["email", "date_of_birth", "password1", "password2"],
                },
            ),
        ]
        search_fields = ["email"]
        ordering = ["email"]
        filter_horizontal = []

    # Now register the new UserAdmin...
    admin.site.register(MyUser, UserAdmin)
    # ... and, since we're not using Django's built-in permissions,
    # unregister the Group model from admin.
    admin.site.unregister(Group)

Akhirnya, tentukan model penyesuaian sebagai model pengguna awal untuk proyek anda menggunakan pengaturan `AUTH_USER_MODEL` di `settings.py` anda:

    AUTH_USER_MODEL = "customauth.MyUser"

#### Adding an async interface

New in Django 5.2.

To optimize performance when called from an async context authentication, backends can implement async versions of each function - `aget_user(user_id)` and `aauthenticate(request, **credentials)`. When an authentication backend extends `BaseBackend` and async versions of these functions are not provided, they will be automatically synthesized with `sync_to_async`. This has performance penalties.

While an async interface is optional, a synchronous interface is always required. There is no automatic synthesis for a synchronous interface if an async interface is implemented.

Django's out-of-the-box authentication backends have native async support. If these native backends are extended take special care to make sure the async versions of modified functions are modified as well.