# Dokumentasi Django 6.0.7

# Transaksi basisdata

Django memberikan anda sedikit cara mengendalikan bagaimana transaksi basisdata dikelola.

## Mengelola transaksi basisdata

### Kebiasaan transaksi awal Django

Kebiasaan awal Django adalah menjalankan suasana penyeraahn otomatis. Setiap query segera diserahkan ke basisdata, meskipun transaksi adalah aktif. Lihat dibawah ini untuk rincian.

Django menggunakan transaksi atau titiksimpan otomatis untuk menjamin kesatuan dari operasi ORM yang membutuhkan banyak query, khususnya query delete() dan update().

Kelas `TestCase` Django juga membungkus setiap percobaan dalam sebuah transaksi untuk alasan penampilan.

### Mengikat transaksi pada permintaan HTTP

Cara umum untuk menangani transaksi di jaringan adalah membungkus setiap permintaan di transaksi. Setel `ATOMIC_REQUESTS` ke `True` di konfigurasi dari setiap basisdata untuk anda ingin adakan kebiasaan ini.

Itu bekerja seperti ini. Sebelum memanggil fungsi tampilan, Django memulai sebuah transaksi. Jika tanggapan adalah dihasilkan tanpa masalah, Django melakukan transaksi. Jika tampilan menghasilkan sebuah pengecualian, Django memutar kembali transaksi.

Anda dapat melakukan subtransaksi menggunakan savepoint dalam kode tampilan anda. khususnya dengan pengelola konteks `atomic()`. Bagaimanapun, pada akhir tampilan, baik semua tau tidak satupun perubahan akan di jalankan.

Peringatan

Selagi kesederhanaan dari model transaksi ini menarik, itu juga membuat itu tidak efesien ketika lalu lintas menarik. Membuka sebuah transaksi untuk setiap tampilan dan beberapa overhead. Dampak pada penampilan bergantingan pada pola permintaan dari aplikasi anda dan pada sebagaimana baik penanganan basisdata anda mengunci.

Transaksi per-permintaan dan mengalirkan tanggapan

Ketika tampilan mengembalikan sebuah `StreamingHttpResponse`, membaca isi dari tanggapan akan sering menjalankan kode untuk membangkitkan isi. Sejak tampilan telah dikembalikan, kode seperti itu berjalan diluar transaksi.

Secara umum, itu tidak disarankan menulis ke basisdata selagi membangkitkan aliran tanggapan, sejak tidak ada cara sepaham menangani kesalahan setelah mulai mengirim tanggapan.

Dalam praktiknya, fitur ini membungkus setiap fungsi tampilan dalam `atomic()` penghias digambarkan dibawah.

Catat bahwa hanya penjalanan dari tampilan anda terlampir dalam transaksi, Middleware berjalan diluar transaksi, dan begitu juga membangun tanggapan-tanggapan cetakan.

Ketika `ATOMIC_REQUESTS` diadakan, itu masih memungkinkan mencegah tampilan dari berjalan dalam sebuah transaksi.

non_atomic_requests(using=None)

  Penghias ini akan meniadakan pengaruh dari `ATOMIC_REQUESTS` untuk tampilan yang diberikan:

      from django.db import transaction

      @transaction.non_atomic_requests
      def my_view(request):
          do_stuff()

      @transaction.non_atomic_requests(using="other")
      def my_other_view(request):
          do_stuff_on_the_other_database()

  Itu hanya bekerja jika itu diberlakukan ke tampilan itu sendiri.

### Mengendalikan transaksi secara eksplisit

Django menyediakan API tunggal untuk mengendalikan transaksi basisdata.

atomic(using=None, savepoint=True, durable=False)

  Atomicity adalah penentuan sifat dari transaksi basisdata. `atomic` mengizinkan kamu membuat blok dari kode dalam yang atomicity pada basisdata dijaminkan. Jika blok dari kode berhasil lengkap, perubahan di perlakukan ke basisdata. Jika ada sebuah pengecualian, perubahan diputar kembali.

  Blok `atomic` dapat bersarang. Dalam kasus ini, ketika sebuah blok sebelah dalam berhasil terpenuhi, pengaruhnya dapat masih di rollback jika sebuah pengecualian dimunculkan di blok sebelah luar pada titik kemudian.

  It is sometimes useful to ensure an `atomic` block is always the outermost `atomic` block, ensuring that any database changes are committed when the block is exited without errors. This is known as durability and can be achieved by setting `durable=True`. If the `atomic` block is nested within another it raises a `RuntimeError`.

  `atomic` is usable both as a decorator:

      from django.db import transaction

      @transaction.atomic
      def viewfunc(request):
          # This code executes inside a transaction.
          do_stuff()

  and as a context manager:

      from django.db import transaction

      def viewfunc(request):
          # This code executes in autocommit mode (Django's default).
          do_stuff()

          with transaction.atomic():
              # This code executes inside a transaction.
              do_more_stuff()

  Membungkus `atomic` dalam sebuah blok try/except mengizinkan untuk penanganan alami dari kesalahan keutuhan:

      from django.db import IntegrityError, transaction

      @transaction.atomic
      def viewfunc(request):
          create_parent()

          try:
              with transaction.atomic():
                  generate_relationships()
          except IntegrityError:
              handle_exception()

          add_children()

  In this example, even if `generate_relationships()` causes a database error by breaking an integrity constraint, you can execute queries in `add_children()`, and the changes from `create_parent()` are still there and bound to the same transaction. Note that any operations attempted in `generate_relationships()` will already have been rolled back safely when `handle_exception()` is called, so the exception handler can also operate on the database if necessary.

  Menghindari menangkap pengecualian didalam `atomic`!

  Ketika mengeluarkan sebuah blok `atomic`, Django mencari apakah itu keluar secara biasa atau dengan sebuah pengecualian untuk menentukan apakah memperlakukan atau memutar kembali. Jika anda menangkap dan menangani pengecualian didalam blok `atomic`, anda mungkin bersembunyi dari Django kenyataan bahwa masalah telah terjadi. Ini dapat menghasilkan perilaku tidak diharapkan.

  Ini kebanyakan perhatian untuk `DatabaseError` dan subkelas-subkelas nya seperti `IntegrityError`. Setelah kesalahan tersebut, transaksi rusak dan Django akan melakukan memutar kembali pada akhir dari blok `atomic`. Jika anda berusaha menjalankan permintaan basisdata sebalum memutar kembali terjadi, Django akan memunculkan sebuah `TransactionManagementError`. Anda mungkin juga menghadapi perilaku ini ketika sinyal terkait-ORM memunculkan sebuah pengecualian.

  Cara benar untuk menangkap kesalahan-kesalahan basisdata disekitar sebuah blok `atomic` seperti ditunjukkan diatas. Jika dibutuhkan, tambah sebuah blok `atomic` tambahan untuk tujuan ini. Pola ini mempunyai keuntungan lain: itu membatasi jelas tindakan-tindakan maan akan diputar kembali jika sebuah pengecualian muncul.

  Jika anda menangkap pengecualian dimunculkan oleh permintaan SQL mentah, perilaku Django tidak ditentukan dan tergantung-basisdata.

  You may need to manually revert app state when rolling back a transaction.

  Nilai-nilai dari bidang-bidang model tidak akan dirubah ketika transaksi memutar kembali terjadi. Ini dapat membawa pada keadaan model tidak tetap meskipun anda secara manual menyimpan kembali nilai-nilai bidang asli.

  Sebagai contoh, diberikan `MyModel` dengan sebuah bidang `active`, potongan ini memastikan bahwa `if obj.active` memeriksa pada akhir penggunaan nilai benar jika memperbaharui `active` menjadi `True` gagal dalam transaksi:

      from django.db import DatabaseError, transaction

      obj = MyModel(active=False)
      obj.active = True
      try:
          with transaction.atomic():
              obj.save()
      except DatabaseError:
          obj.active = False

      if obj.active:
          ...

  This also applies to any other mechanism that may hold app state, such as caching or global variables. For example, if the code proactively updates data in the cache after saving an object, it's recommended to use transaction.on_commit() instead, to defer cache alterations until the transaction is actually committed.

  Untuk menjamin atomicity, `atomic` meniadakan beberapa API. Berusaha memperlakukan, memutar kembali, atau merubah keadaan penjalanan otomatis dari hubungan basisdata dalam sebuah blok `atomic` akan memunculkan sebuah pengecualian.

  `atomic` mengambil sebuah argumen `using` yang harus berupa nama dari basisdata. Jika argumen ini tidak disediakan, Django menggunakan basisdata `"default"`.

  Dibawah tenda, kode pengelolaan transaksi Django:

  - membuka sebuah transaksi ketika memasukkan blok `atomic` paling luar;

  - membuat titik simpan ketika memasukkan blok `atomic` sebelah dalam;

  - melepaskan atau digulung kembali ke titik simpan ketika keluar blok paling dalam;

  - menyerahkan atau gulung kembali transaksi ketika keluar blok paling luar

  Anda dapat meniadakan pembuatan dari titik simpan untuk blok sebelah dalam dengan mengatur argumen `savepoint` ke `False`. Jika sebuah pengecualian muncul, Django akan melakukan gulunh kembali ketika keluar blok induk pertama dengan sebuah titik simpan jika ada, dan blok paling luar jika tidak. Atomicity masih dijamin oleh transaksi paling luar. Pilihan ini harus hanya digunakan jika kelebihan dari titik simpan dapat dilihat. Itu mempunyai kekurangan dari memecahkan penanganan kesalahan yang digambarkan diatas.

  Anda dapat menggunakan `atomic` ketika penyerahan otomatis dimatikan. Itu akan hanya menggunakan titik simpan, bahkan untuk blok paling luar.

Pertimbangan penampilan

Transaksi-transaksi terbuka mempunyai biaya penampilan untuk peladen basisdata anda. Untuk meminimalkan overhead ini, jaga transaksi-transaksi anda sependek mungkin. Ini adalah khususnya penting jika anda sedang menggunakan `atomic()` dalamn pengolahan berjalan-panjang, diluar permintaan Django / siklus tanggapan.

## Penyerahan otomatis

### Kenapa Django menggunakan penyerahan otomatis

Dalam standar SQL, setiap permintaan SQL memulai sebuah transaksi, meskipun satu sudah aktif. Transaksi tersebut harus secara eksplisit diserahkan dan digulung kembali.

Ini tidak selalu mudah untuk pengembang aplikasi. Untuk meredakan masalah ini, kebanyakan basisdata menyediakan sebuah suasana penyerahan otomatis. Ketika penyerahan otomatis dinayalan dan tidak ada transaksi aktif, setiap permintaan SQL dibungkus dalam transaksinya sendiri. Dengan kata lain, bukan hanya melakukan setiap permintaan tersebut mulai sebuah transaksi, tetapi transaksi juga mendapatkan otomatis diserahkan atau digulung kembali, tergandunt pada apakah permintaan berhasil.

PEP 249, Spesifikasi API Basisdata Python v2.0, membutuhkan penjalanan otomatis untuk diawalkan dimatikan. Django menimpa awalan ini dan menyalakan penjalanan otomatis.

Untuk menghindari ini, anda dapat menonaktifkan pengelolaan transaksi, tetapi itu sangat tidak dianjurkan.

### Menonaktifkan pengelolaan transaksi

Anda dapat sama sekali meniadakan pengelolaan transaksi Django untuk basis data diberikan dengan mengatur `AUTOCOMMIT 1` menjadi `False` dalam konfigurasinya. Jika anda melakukan ini, Django tidak akan mengadakan autocommit, dan tidak akan melakukan penjalanan apapun. Anda akan mendapatkan perilaku biasa dari pustaka basisdata pokok.

Ini membutuhkan anda untuk menyerahkan secara eksplisit setiap transaksi, bahkan yang dimulai oleh Django atau oleh pustaka pihak ketiga. Jadi, ini adalah penggunaan terbaik dalam keadaan dimana anda ingin menjalankan middleware pengendalian transaksi milik anda atau melakukan sesuatu yang sangat aneh.

## Melakukan tindakan setelah penyerahan

Sometimes you need to perform an action related to the current database transaction, but only if the transaction successfully commits. Examples might include a background task, an email notification, or a cache invalidation.

`on_commit()` allows you to register callbacks that will be executed after the open transaction is successfully committed:

on_commit(func, using=None, robust=False)

Pass a function, or any callable, to `on_commit()`:

    from django.db import transaction

    def send_welcome_email(): ...

    transaction.on_commit(send_welcome_email)

Callbacks will not be passed any arguments, but you can bind them with `functools.partial()`:

    from functools import partial

    for user in users:
        transaction.on_commit(partial(send_invite_email, user=user))

Callbacks are called after the open transaction is successfully committed. If the transaction is instead rolled back (typically when an unhandled exception is raised in an `atomic()` block), the callback will be discarded, and never called.

If you call `on_commit()` while there isn't an open transaction, the callback will be executed immediately.

It's sometimes useful to register callbacks that can fail. Passing `robust=True` allows the next callbacks to be executed even if the current one throws an exception. All errors derived from Python's `Exception` class are caught and logged to the `django.db.backends.base` logger.

You can use `TestCase.captureOnCommitCallbacks()` to test callbacks registered with `on_commit()`.

### Savepoint

Titik simpan (yaitu blok `atomic()` bersarang) ditangani dengan benar. Yaitu, sebuah `on_commit()` callable terdaftar setelah sebuah titik simpan (dalam blok `atomic()` bersarang) akan dipanggil setelah transaksi paling luar diserahkan, tetapi tidak jika disimpan kembali ke titik simpan tersebut atau titik simpan sebelumnya yang muncul selama transaksi:

    with transaction.atomic():  # Outer atomic, start a new transaction
        transaction.on_commit(foo)

        with transaction.atomic():  # Inner atomic block, create a savepoint
            transaction.on_commit(bar)

    # foo() and then bar() will be called when leaving the outermost block

Pada sisi lain, ketika sebuah titik simpan disimpan kembali (karena sebuah pengecualian telah dimunculkan), sebe;ah dalam dapat dipanggil tidak akan dipanggil:

    with transaction.atomic():  # Outer atomic, start a new transaction
        transaction.on_commit(foo)

        try:
            with transaction.atomic():  # Inner atomic block, create a savepoint
                transaction.on_commit(bar)
                raise SomeError()  # Raising an exception - abort the savepoint
        except SomeError:
            pass

    # foo() will be called, but not bar()

### Urutan pelaksanaan

On-commit functions for a given transaction are executed in the order they were registered.

### Penanganan pengecualian

If one on-commit function registered with `robust=False` within a given transaction raises an uncaught exception, no later registered functions in that same transaction will run. This is the same behavior as if you'd executed the functions sequentially yourself without `on_commit()`.

### Waktu pelaksanaan

Your callbacks are executed after a successful commit, so a failure in a callback will not cause the transaction to roll back. They are executed conditionally upon the success of the transaction, but they are not part of the transaction. For the intended use cases (mail notifications, background tasks, etc.), this should be fine. If it's not (if your follow-up action is so critical that its failure should mean the failure of the transaction itself), then you don't want to use the `on_commit()` hook. Instead, you may want two-phase commit such as the psycopg Two-Phase Commit protocol support and the optional Two-Phase Commit Extensions in the Python DB-API specification.

Callback tidak berjalan sampai perbaikan otomatis dipulihkan pada hubungan perbaikan berikut (karena sebaliknya apapun permintaan selesai dalam sebuah callback akan membuka sebuah transaksi tersirat, mencegah hubungan dari kembali kedalam suasana perbaikan otomatis).

Ketika dalam suasana penjalan otomatis dan diluar dari blok `atomic()`, fungsi akan berjalan segera tidak pada penjalanan.

On-commit functions only work with autocommit mode and the `atomic()` (or `ATOMIC_REQUESTS`) transaction API. Calling `on_commit()` when autocommit is disabled and you are not within an atomic block will result in an error.

### Digunakan dalam percobaan

Django's `TestCase` class wraps each test in a transaction and rolls back that transaction after each test, in order to provide test isolation. This means that no transaction is ever actually committed, thus your `on_commit()` callbacks will never be run.

You can overcome this limitation by using `TestCase.captureOnCommitCallbacks()`. This captures your `on_commit()` callbacks in a list, allowing you to make assertions on them, or emulate the transaction committing by calling them.

Another way to overcome the limitation is to use `TransactionTestCase` instead of `TestCase`. This will mean your transactions are committed, and the callbacks will run. However `TransactionTestCase` flushes the database between tests, which is significantly slower than `TestCase`'s isolation.

### Why no rollback hook?

A rollback hook is harder to implement robustly than a commit hook, since a variety of things can cause an implicit rollback.

Sebagai contoh, jika hubungan basisdata anda jatuh karena pengolahan anda mati tanpa kesempatan dimatikan dengan anggun, hubungan memutar kembali anda tidak pernah berjalan,

But there is a solution: instead of doing something during the atomic block (transaction) and then undoing it if the transaction fails, use `on_commit()` to delay doing it in the first place until after the transaction succeeds. It's a lot easier to undo something you never did in the first place!

## API tingkat-rendah

Peringatan

Selalu memilih `atomic()` jika memungkan sama sekali. Itu menghitung untuk keanehan dari setiap basisdata dan mecegah tindakan-tindakan tidak sah.

API tingkat rendah hanya berguna jika anda sedang menerapkan pengelolaan transaksi anda sendiri.

### Penyerahan otomatis

Django provides an API in the `django.db.transaction` module to manage the autocommit state of each database connection.

get_autocommit(using=None)

set_autocommit(autocommit, using=None)

Fungsi-fungsi ini mengambil sebuah argumen `using` yang harus berupa nama dari basisdata. Jika itu tidak disediakan, Django menggunakan basisdata `"default"`.

Autocommit awalannya dinyalakan. Jika anda mematikan itu, itu adalah tanggungjawab anda menyimpan itu kembali.

Sekali anda mematikan autocommit, anda mendapatkan perilaku awalan dari penyadur basisdata anda, dan Django tidak akan membantu anda. Meskipun perilaku itu adalah ditentukan dalam PEP 249, penerapan dari penyadur tidak selalu konsisten dengan satu lainnya. Tinjau kembali dari penyadur anda sedang gunakan secara hati-hati.

Anda harus memastikan bahwa tidak ada transaksi aktif, biasanya dengan menerbitkan `commit()` or a `rollback()`, sebelum menyalakan penjalanan otomatis.

Django akan menolak mematikan autocommit ketika blok `atomic()` aktif, karena itu akan merusak atomicity.

### Transaksi

Sebuah transaksi adalah atomic kumpulan dari permintaan basisdata. Bahkan jika program anda tabrakan, basisdata menjamin bahwa baik semua perubahan akan diberlakukan, atau tidak dari mereka.

Django tidak menyediakan sebuah API untuk memulai sebuah transaksi. Cara diharapkan memulai sebuah transaksi adalah meniadakan autocommit dengan `set_autocommit()`.

Sekali anda berada dalam transaksi, anda dapat memilih antara memberlakukan perubahan anda telah lakukan sampai titik ini dengan `commit()`, atau mmebatalkan mereka dengan `rollback()`. Fungsi-fungsi ini ditentukan dalam `django.db.transaction`.

commit(using=None)

rollback(using=None)

Fungsi-fungsi ini mengambil sebuah argumen `using` yang harus berupa nama dari basisdata. Jika itu tidak disediakan, Django menggunakan basisdata `"default"`.

Django menolak commit atau rollback ketika sebuah blok `atomic()` aktif, karena itu akan merusak atomicity.

### Savepoint

A savepoint is a marker within a transaction that enables you to roll back part of a transaction, rather than the full transaction. Savepoints are available with the SQLite, PostgreSQL, Oracle, and MySQL (when using the InnoDB storage engine) backends. Other backends provide the savepoint functions, but they're empty operations -- they don't actually do anything.

Savepoint bukanlah khususnya berguna jika anda sedang menggunakan autocommit, perilaku kebiasaan dari Django. Bagaimanapun, sekali anda membuka sebuah transaksi dengan `atomic()`, anda membangun deretan tindakan-tindakan basisdata menunggu sebuah commit atau rollback. Jika anda menerbitkan sebuah rollback, transaksi keseluruhan diputar kembali yang akan dilakukan dengan `transaction.rollback()`.

Ketika penghias `atomic()` bersarang, itu membuat sebuah savepoint untuk mengizinkan commit atau rollback sebagian. Anda sangat dianjurkan menggunakan `atomic()` daripada fungsi-fungsi digambarkan dibawah, tetapi mereka adalah masih bagian dari API umum, dan tidak ada rencana mengusangkan mereka.

Each of these functions takes a `using` argument which should be the name of a database for which the behavior applies. If no `using` argument is provided then the `"default"` database is used.

Savepoint dikendalikan oleh tiga fungsi dalam `django.db.transaction`:

savepoint(using=None)

  Ditinggalkan sejak versi 6.1: `savepoint` has been renamed to `savepoint_create`.

  Membuat sebuah savepoint baru. Ini menandai sebuah titik dalam transaksi yang dikenal sebagai keadaan "good". Mengembalikan ID savepoint (`sid`).

savepoint_create(using=None)
  New in Django 6.1.

  Membuat sebuah savepoint baru. Ini menandai sebuah titik dalam transaksi yang dikenal sebagai keadaan "good". Mengembalikan ID savepoint (`sid`).

savepoint_commit(sid, using=None)

  Bebaskan savepoint `sid`. Perubahan dilakukan sejak savepoint dibuat menjadi bagian dari transaksi.

savepoint_rollback(sid, using=None)

  Memutar kembali transaksi pada savepoint `sid`.

Fungsi-fungsi ini tidak melakukan apapun jika savepoint tidak didukung atau jika basisdata dalam suasana penjalanan otomatis.

Sebagai tambahan, ada fungsi kegunaan:

clean_savepoints(using=None)

  Setel kembali penghitung digunakan untuk membangkitkan ID savepoint unik.

Contoh berikut mempertunjukkan penggunaan dari savepoint:

    from django.db import transaction

    # open a transaction
    @transaction.atomic
    def viewfunc(request):
        a.save()
        # transaction now contains a.save()

        sid = transaction.savepoint_create()

        b.save()
        # transaction now contains a.save() and b.save()

        if want_to_keep_b:
            transaction.savepoint_commit(sid)
            # open transaction still contains a.save() and b.save()
        else:
            transaction.savepoint_rollback(sid)
            # open transaction now contains only a.save()

Savepoint dapat digunakan untuk memulihkan dari kesalahan basisdata dengan melakukan rollback sebagian. Jika anda sedang melakukan ini didalam sebuah blok `atomic()`, keseluruhan blok akan masih dapat di rollback, karena itu tidak mengetahui anda telah menangani keadaan pada tingkatan terendah! Untuk mencegah ini, anda dapat mengendalikan perilaku rollback dengan fungsi-fungsi berikut.

get_rollback(using=None)

set_rollback(rollback, using=None)

Setel bendera rollback menjadi `True` memaksa sebuah rollback ketika keluar blok atomik paling sebelah dalam. Ini mungkin berguna untuk memicu sebuah rollback tanpa memunculkan sebuah pengecualian.

Setel itu menjadi `False` mencegah rollback seperti itu. Sebelum melakukan itu, pastikan anda telah rollback transaksi pada savepoint dikenal-baik dalam blok atomic saat ini! Sebaliknya anda sedang merusak atomic dan kerusakan data mungkin muncul.

## Catatan khusus-basisdata

### Savepoint di SQLite

While SQLite supports savepoints, a flaw in the design of the `sqlite3` module makes them hardly usable.

Ketika autocommit diadakan, savepoint tidak masuk akal. Ketika itu ditiadakan, `sqlite3` commit secara mutlak sebelum pernyataan savepoint. (Dalam faktanya, itu commit sebelum pernyataan apapun selain dari `SELECT`, `INSERT`, `UPDATE`, `DELETE` dan `REPLACE`.) Kesalahan ini memiliki dua konsekuensi:

- The low level APIs for savepoints are only usable inside a transaction i.e. inside an `atomic()` block.

- Sangat tidak mungkin menggunakan `atomic()` ketika penjalan otomatis dimatikan.

### Transaksi di MySQL

Jika anda sedang menggunakan MySQL, tabel-tabel anda mungkin atau mungkin tidak mendukung transaksi; itu tergantung pada versi MySQL anda dan jenis-jenis tabel anda sedang gunakan. (Berdasarkan "table types," kami artikan sesuatu seperti "InnoDB" or "MyISAM".) Kekhasan transaksi MySQL adalah diluar cakupan dari artikel ini, tetapi situs MySQL mempunyai information on MySQL transactions.

Jika pengaturan MySQL anda tidak mendukung transaksi, kemudian Django akan selalu menggunakan suasana penjalan otomatis: pernyataan-pernyataan akan dijalankan dan diperlakukan segera mereka dipanggil. Jika pengaturan MySQL anda melakukan mendukung transaksi, Django akan menangani transaksi-transaksi seperti dijelaskan dalam dokumen ini.

### Penanganan pengecualian dalam transaksi PostgreSQL

Catatan

Bagian ini hanya bersangkut paut hanya jika anda sedang menerapkan pengelolaan transaksi anda sendiri. Masalah ini tidak dapat muncul dalam keadaan awalan Django dan `atomic()` menangani itu otomatis.

Inside a transaction, when a call to a PostgreSQL cursor raises an exception (typically `IntegrityError`), all subsequent SQL in the same transaction will fail with the error "current transaction is aborted, queries ignored until end of transaction block". While the basic use of `save()` is unlikely to raise an exception in PostgreSQL, there are more advanced usage patterns which might, such as saving objects with unique fields, saving using the `force_insert`/`force_update` flag, or invoking custom SQL.

Ada beberapa cara memulihkan dari urutan kesalahan ini.

#### Gulung kembali transaksi

Pilihan pertama adalah memutar kembali transaksi keseluruhan. Sebagai contoh:

    a.save()  # Succeeds, but may be undone by transaction rollback
    try:
        b.save()  # Could throw exception
    except IntegrityError:
        transaction.rollback()
    c.save()  # Succeeds, but a.save() may have been undone

Memanggil memutar kembali `transaction.rollback()` keseluruhan transaksi. Apapun tindakan basisdata tidak di commit akan hilang. Dalam contoh ini, perubahan dibuat oleh `a.save()` akan hilang, meski pekerjaan itu tidak memunculkan kesalahan itu sendiri.

#### Memutar kembali savepoint

Anda dapat menggunakan savepoints 1 untuk mengendalikan tingkat dari memutar kembali. Sebelum melakukan tindakan basisdata yang dapat gagal, anda dapat menyetel atau memperbaharui savepoint; cara itu, jika tindakan gagal, anda dapat memutar kembali tindakan tunggal menyinggung, daripada transaksi keseluruhan. Sebagai contoh:

    a.save()  # Succeeds, and never undone by savepoint rollback
    sid = transaction.savepoint_create()
    try:
        b.save()  # Could throw exception
        transaction.savepoint_commit(sid)
    except IntegrityError:
        transaction.savepoint_rollback(sid)
    c.save()  # Succeeds, and a.save() is never undone

Dalam contoh ini, `a.save()` tidak akan dilepas dalam kasus dimana `b.save()` memunculkan sebuah pengecualian.