Lewati ke isi

sinyal

Sinyal adalah mekanisme yang memicu kode Anda (fungsi / metode) setiap kali jenis peristiwa tertentu terjadi di ormar.

Oleh karena itu, Anda perlu mendaftarkan penerima untuk jenis sinyal yang diberikan dari model yang dipilih.

Tentukan penerima

Contoh model berikut diberikan:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Basis data impor
meter persegi import

Asrama impor


base _ ormar _ config = ormar. OrmarConfig (
    Database = database. Database ("sqlite: / / db.sqlite"),
    Metadata = sqlalchemy. MetaData (),
)


Album Kelas (ormar. Model):
    ormar _ config = base _ ormar _ config copy ()

    Id: int = ormar. Integer (primary _ key = Benar)
    Nama: str = ormar. String (max _ length = 100)
    is _ best _ seller: bool = ormar. Boolean (default = Salah)
    Play _ count: int = ormar. Integer (default = 0)

Misalnya, Anda dapat menentukan pemicu yang menetapkan album.is\ _ best\ _ seller state jika album dimainkan lebih dari 50 kali.

Impor dekorator pra\ _ pembaruan dan lihat daftar dekorator / sinyal yang tersedia saat ini di bawah ini.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import asyncio

import databases
import ormar
import sqlalchemy
from examples import create_drop_database
from ormar import pre_update

DATABASE_URL = "sqlite:///test.db"

ormar_base_config = ormar.OrmarConfig(
    database=databases.Database(DATABASE_URL),
    metadata=sqlalchemy.MetaData(),
)


class Album(ormar.Model):
    ormar_config = ormar_base_config.copy(
        tablename="albums",
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    is_best_seller: bool = ormar.Boolean(default=False)
    play_count: int = ormar.Integer(default=0)


@pre_update(Album)
async def before_update(sender, instance, **kwargs):
    if instance.play_count > 50 and not instance.is_best_seller:
        instance.is_best_seller = True


@create_drop_database(base_config=ormar_base_config)
async def run_query():
    # here album.play_count ans is_best_seller get default values
    album = await Album.objects.create(name="Venice")
    assert not album.is_best_seller
    assert album.play_count == 0

    album.play_count = 30
    # here a trigger is called but play_count is too low
    await album.update()
    assert not album.is_best_seller

    album.play_count = 60
    await album.update()
    assert album.is_best_seller


asyncio.run(run_query())

Tentukan fungsi Anda.

Harap dicatat bahwa setiap penerima memiliki fitur:

  • Harus dapat dipanggil
  • Harus menerima argumen pengirim pertama dari kelas objek terima-kirim
  • harus menerima argumen kwargs**sebagai argumen yang di kirim di setiap ormar. Sinyal dapat berubah kapan saja, jadi fungsi Anda harus melayani mereka.
  • Itu pasti asinkron karena panggilan balik dikumpulkan dan menunggu.

Pra\ _ pembaruan saat ini hanya mengirimkan satu parameter selain pengirim, dan ini adalah contoh satu.

Perhatikan bagaimana dekorator pra\ _ pembaruan menerima parameter pengirim, yang dapat berupa model tunggal atau daftar model yang ingin Anda jalankan penerima sinyal.

Saat ini, tidak mungkin untuk mengatur sinyal untuk semua model segera tanpa secara eksplisit meneruskan semua model ke registri penerima.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import asyncio

import databases
import ormar
import sqlalchemy
from examples import create_drop_database
from ormar import pre_update

DATABASE_URL = "sqlite:///test.db"

ormar_base_config = ormar.OrmarConfig(
    database=databases.Database(DATABASE_URL),
    metadata=sqlalchemy.MetaData(),
)


class Album(ormar.Model):
    ormar_config = ormar_base_config.copy(
        tablename="albums",
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    is_best_seller: bool = ormar.Boolean(default=False)
    play_count: int = ormar.Integer(default=0)


@pre_update(Album)
async def before_update(sender, instance, **kwargs):
    if instance.play_count > 50 and not instance.is_best_seller:
        instance.is_best_seller = True


@create_drop_database(base_config=ormar_base_config)
async def run_query():
    # here album.play_count ans is_best_seller get default values
    album = await Album.objects.create(name="Venice")
    assert not album.is_best_seller
    assert album.play_count == 0

    album.play_count = 30
    # here a trigger is called but play_count is too low
    await album.update()
    assert not album.is_best_seller

    album.play_count = 60
    await album.update()
    assert album.is_best_seller


asyncio.run(run_query())

!!!Perhatikan bahwa penerima didefinisikan pada tingkat kelas - >, jadi meskipun Anda menghubungkan / memutuskan fungsi melalui instance, itu akan menjalankan / menghentikan semua operasi di ormar itu. Kelas model.

Harap dicatat bahwa fungsi kami yang baru dibuat memiliki contoh dan kelas contoh, sehingga Anda dapat dengan mudah menjalankan kueri database di dalam wastafel jika Anda mau.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import asyncio

import databases
import ormar
import sqlalchemy
from examples import create_drop_database
from ormar import pre_update

DATABASE_URL = "sqlite:///test.db"

ormar_base_config = ormar.OrmarConfig(
    database=databases.Database(DATABASE_URL),
    metadata=sqlalchemy.MetaData(),
)


class Album(ormar.Model):
    ormar_config = ormar_base_config.copy(
        tablename="albums",
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    is_best_seller: bool = ormar.Boolean(default=False)
    play_count: int = ormar.Integer(default=0)


@pre_update(Album)
async def before_update(sender, instance, **kwargs):
    if instance.play_count > 50 and not instance.is_best_seller:
        instance.is_best_seller = True


@create_drop_database(base_config=ormar_base_config)
async def run_query():
    # here album.play_count ans is_best_seller get default values
    album = await Album.objects.create(name="Venice")
    assert not album.is_best_seller
    assert album.play_count == 0

    album.play_count = 30
    # here a trigger is called but play_count is too low
    await album.update()
    assert not album.is_best_seller

    album.play_count = 60
    await album.update()
    assert album.is_best_seller


asyncio.run(run_query())

Anda dapat menentukan penerima yang sama untuk beberapa model sekaligus dengan memberikan daftar model ke dekorator sinyal.

1
2
3
4
# menentukan fungsi debug boneka
@ pra _ pembaruan ([Album, Lagu])
Async def sebelum _ update (pengirim, contoh, * * kwargs):
    Cetak (f "{sender.get_name()}:{instance.model_dump_json()}:{kwargs}")

Tentu saja, Anda juga dapat membuat beberapa fungsi untuk sinyal dan model yang sama. Masing-masing akan berjalan pada setiap sinyal.

1
2
3
4
5
6
7
@ pra _ pembaruan (Album)
Async def sebelum _ update (pengirim, contoh, * * kwargs):
    Cetak (f "{sender.get_name()}:{instance.model_dump_json()}:{kwargs}")

@ pra _ pembaruan (Album)
Sinkronisasi def sebelum _ update2 (pengirim, contoh, * * kwargs):
    Cetak (f 'Akan memperbarui{sender.get_name()}dengan pk:{instance.pk}')

Harap dicatat bahwa dekorator ormar adalah gula sintaksis, dan Anda dapat langsung menghubungkan fungsi atau metode sinyal yang diberikan untuk model tertentu. Connect hanya membutuhkan satu argumen - fungsi / metode penerima Anda.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
AlbumAuditor Kelas:
    Def _ _ init _ _ (diri):
        Acara self.event _ type = "ALBUM _ INSTANCE"

    Sinkronisasi def sebelum _ simpan (diri, pengirim, contoh, * * kwargs):
        Menunggu AuditLog (
            event _ type = f "{self.event_type}_ SAVE," event _ log = instance. model _ dump _ json ()
        ).simpan ()

Auditor = AlbumAuditor ()
pra _ simpan (Album) (auditor. sebelum _ simpan)
# Panggilan di atas memiliki hasil yang sama seperti di bawah ini
ormar _ config signal pre _ save connect (auditor sebelum _ save)
# sinyal juga terungkap pada contoh
Album = Album (nama = 'Miami')
Album.signals.pre _ save connect (auditor. sebelum _ save)

!!! Peringatan Harap dicatat bahwa sinyal menyimpan referensi ke penerima (bukan referensi yang lemah), jadi ingatlah ini untuk menghindari referensi melingkar.

Putuskan sambungan penerima

Untuk melepaskan penerima dan menghentikannya menjalankan model tertentu, Anda harus melepaskannya.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@ pra _ pembaruan (Album)
Async def sebelum _ update (pengirim, contoh, * * kwargs):
    Jika instan. play _ count > 50 dan tidak instance. is _ best _ seller:
        Instance. is _ best _ seller = Benar

# putuskan fungsi yang diberikan dari sinyal untuk Model yang diberikan
Album. ormar _ config signal. pra _ simpan (sebelum _ simpan)
# sinyal juga terungkap pada contoh
Album = Album (nama = 'Miami')
Album.signals.pre _ save putuskan sambungan (sebelum _ simpan)

sinyal yang tersedia

!!!Peringatan, harap dicatat bahwa tidak ada sinyal yang akan di kirim.

1
2
3
4
Operasi massal*  (`QuerySet.bulk_create` dan `QuerySet.bulk_update`) karena dirancang untuk kecepatan.

*  Operasi tingkat meja QuerySet (`QuerySet.update` dan `QuerySet.delete`) saat mereka berjalan di atas meja yang mendasarinya 
(Lebih seperti operasi pembaruan / penghapusan sql mentah) dan tidak memiliki contoh khusus.

pra-simpan

pre_save(sender: Type["Model"], instance: "Model")

Kirim Model.save () dan metode Model.objeks.create ().

Pengirim adalah ormar. Kelas model, contoh model yang akan disimpan.

Setelah menabung

post_save(sender: Type["Model"], instance: "Model")

Kirim Model.save () dan metode Model.objeks.create ().

Pengirim adalah ormar. Kelas model, contoh model yang disimpan.

pra-pembaruan

pre_update(sender: Type["Model"], instance: "Model")

Di kirim ke metode Model.update ().

Pengirim adalah ormar. Kelas model, contoh model yang akan diperbarui.

Setelah pembaruan

post_update(sender: Type["Model"], instance: "Model")

Di kirim ke metode Model.update ().

Pengirim adalah ormar. Kelas model, contoh model yang diperbarui.

pra-hapus

pre_delete(sender: Type["Model"], instance: "Model")

Kirim Model.save () dan metode Model.objeks.create ().

Pengirim adalah ormar. Kelas model, contoh model yang akan dihapus.

setelah penghapusan

post_delete(sender: Type["Model"], instance: "Model")

Di kirim ke metode Model.update ().

Pengirim adalah ormar. Kelas model, contoh model yang dihapus.

penambahan pra-hubungan

pre_relation_add(sender: Type["Model"], instance: "Model", child: "Model", relation_name: str, passed_args: Dict)

Mengirimkan metode Model.relation\ _ name () dari hubungan banyak-ke-banyak dan kebalikan dari hubungan kunci asing.

Pengirim - kelas pengirim, misalnya - tambahkan contoh model terkait, model anak ditambahkan, hubungan\ _ nama - nama relasi untuk menambah anak, juga dilewatkan untuk menambahkan sinyal\ _ kwargs - kamus kwarg dilewatkan untuk menambahkan ()

pasca hubungan tambahkan

post_relation_add(sender: Type["Model"], instance: "Model", child: "Model", relation_name: str, passed_args: Dict)

Mengirimkan metode Model.relation\ _ name () dari hubungan banyak-ke-banyak dan kebalikan dari hubungan kunci asing.

Pengirim - kelas pengirim, misalnya - tambahkan contoh model terkait, model anak ditambahkan, hubungan\ _ nama - nama relasi untuk menambah anak, juga dilewatkan untuk menambahkan sinyal\ _ kwargs - kamus kwarg dilewatkan untuk menambahkan ()

penghapusan pra-hubungan

pre_relation_remove(sender: Type["Model"], instance: "Model", child: "Model", relation_name: str)

Mengirimkan metode Model.relation\ _ name () dari hubungan banyak-ke-banyak dan kebalikan dari hubungan kunci asing.

Pengirim - Kelas pengirim, misalnya - Tambahkan contoh model terkait, anak - Model ditambahkan, hubungan\ _ nama - Nama relasi untuk menambah anak.

Setelah menghapus hubungan

post_relation_remove(sender: Type["Model"], instance: "Model", child: "Model", relation_name: str, passed_args: Dict)

Mengirimkan metode Model.relation\ _ name () dari hubungan banyak-ke-banyak dan kebalikan dari hubungan kunci asing.

Pengirim - Kelas pengirim, misalnya - Tambahkan contoh model terkait, anak - Model ditambahkan, hubungan\ _ nama - Nama relasi untuk menambah anak.

Setelah pembaruan batch

post_bulk_update(sender: Type["Model"], instances: List["Model"], **kwargs), di kirim ke metode Model.objects.bulk_update(List[objects]).

Tentukan sinyal Anda sendiri

Harap dicatat bahwa Anda dapat membuat sinyal Anda sendiri, meskipun Anda harus mengirimkannya secara manual dalam kode atau subclass ormar. Model dan picu sinyal di sana.

Membuat sinyal baru itu sederhana. Contoh berikut mengatur sinyal baru bernama sinyal\ _ custom\ _ Anda.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
Basis data impor
meter persegi import

Asrama impor


base _ ormar _ config = ormar. OrmarConfig (
    Database = database. Database ("sqlite: / / db.sqlite"),
    Metadata = sqlalchemy. MetaData (),
)


Album Kelas (ormar. Model):
    ormar _ config = base _ ormar _ config copy ()

    Id: int = ormar. Integer (primary _ key = Benar)
    Nama: str = ormar. String (max _ length = 100)
    is _ best _ seller: bool = ormar. Boolean (default = Salah)
    Play _ count: int = ormar. Integer (default = 0)

Album. ormar _ config signal. your _ custom _ signal = ormar. Sinyal ()
ormar _ konfigurasi sinyal _ kustom _ koneksi sinyal Anda (nama _ penerima _ Anda)

Faktanya, lapisan bawah sinyal adalah instance SignalEmitter yang menyimpan kamus sinyal yang diketahui dan memungkinkan Anda mengaksesnya sebagai properti. Saat Anda mencoba mengakses sinyal yang tidak ada, SignalEmitter akan membuat sinyal untuk Anda.

Jadi contoh di atas dapat disederhanakan menjadi. Sinyal akan dibuat untuk Anda.

1
ormar _ konfigurasi sinyal _ kustom _ koneksi sinyal Anda (nama _ penerima _ Anda)

Sekarang untuk memicu sinyal ini, Anda perlu menghubungi metode pengiriman sinyal.

1
Tunggu Album. ormar _ config signal. your _ custom _ signal send (pengirim = Album)

Harap dicatat bahwa pengirim adalah satu-satunya parameter yang diperlukan, dan itu harus menjadi kelas Model Ormar.

Parameter tambahan harus dilewatkan sebagai argumen kata kunci.

1
Await Album. ormar _ config signal. your _ custom _ signal send (pengirim = Album, my _ param = Benar)