Ommaviy amallar
Qatorlar belgilanganda paydo bo‘ladigan panel — buni qanday e’lon qilish, u ishlaydigan tranzaksiya va amallarni umuman ko‘rsatmaslik haqida.
Mavjud v0.1.0
Qatorni belgilang — jadval ustida panel paydo bo‘ladi. delete o‘rnatilgan va
sukut bo‘yicha yoqilgan; qolgan barchasi — ModelAdmin dagi metodlar.
@admin.register(Product, key="catalog.product")
class ProductAdmin(admin.ModelAdmin):
actions = ("delete", "activate", "mark_discontinued")
@admin.action("Activate", icon="check-circle")
async def activate(self, adapter, objects):
for product in objects:
await adapter.update(product, {"is_active": True})
return f"{len(objects)} products activated."
Dekorator o‘zida yorliq va ikonkani olib yuradi, shuning uchun ular amalni amalga oshiruvchi koddan chetlashib keta olmaydi — aynan shu narsaga metod nomlarini alohida ro‘yxatda sanab chiqish yo‘l qo‘yardi.
@admin.action(label, *, icon=None, danger=False, confirm=None)
label | Tugmada yozilgan matn |
icon | fastfort.ui.icons dagi nom, e’lon qilish vaqtida tekshiriladi |
danger | Xavf rangida chiziladi va bajarishdan oldin tasdiq so‘raydi |
confirm | Savol matni. {count} o‘rniga qiymat qo‘yiladi |
@admin.action(
"Mark discontinued",
icon="trash",
danger=True,
confirm="Mark {count} products discontinued? They will stop appearing in the shop.",
)
async def mark_discontinued(self, adapter, objects):
for product in objects:
await adapter.update(
product, {"availability": Availability.DISCONTINUED, "is_active": False}
)
return f"{len(objects)} products discontinued."
Signatura
async def handler(self, adapter, objects) -> str: ...
adapter — shu model uchun mo‘ljallangan, joriy so‘rovning ish birligiga
(unit of work) bog‘langan ModelAdapter. objects — belgilangan va
allaqachon yuklangan qatorlar. Qaytarilgan qiymat — keyin ko‘rsatiladigan
xabar.
U hech qachon commit qilmaydi
Bu joyni yaxshilab tushunib olish kerak. Adapter flush qiladi; so‘rovning
UnitOfWorki muvaffaqiyatli yakunlanganda commit qiladi, xatolik yuz bersa —
rollback qiladi. Shu sababli qirqinchi qatorda muvaffaqiyatsizlikka uchragan
amal dastlabki o‘ttiz to‘qqiztasini ham yozilmagan holda qoldiradi — bu esa
ommaviy operatsiyadan deyarli har doim kutilgan natija, alohida saqlashlar
siklidan olinadigan natija esa bunday emas.
@admin.action("Recalculate totals")
async def recalculate(self, adapter, objects):
for invoice in objects:
# If this raises on invoice 40, invoices 1–39 are rolled back with it.
await adapter.update(invoice, {"total": compute_total(invoice)})
return f"{len(objects)} invoices recalculated."
commit()ni o‘zingiz chaqirmang. Bunday qilish so‘rovni ikkita tranzaksiyaga
bo‘lib yuboradi va bu kafolatni undan keyingi hamma narsa uchun buzadi.
Hech narsa taklif qilmaslik
actions = ()
Panel hech qachon paydo bo‘lmaydi. Qatorlari ommaviy tarzda o‘chirilishi mumkin bo‘lmagan model buni aynan shunday bildiradi — har bir qatorning o‘chirish tugmasiga bu ta’sir qilmaydi.
@admin.register(ApiToken, key="accounts.token")
class ApiTokenAdmin(admin.ModelAdmin):
actions = ()
Chaqirish imkoniyati
@admin.action bilan belgilangan, ammo actions ro‘yxatiga kiritilmagan
metod nomini yuborish orqali chaqirib bo‘lmaydi. Tekshiruv e’lon qilingan
ro‘yxat asosida olib boriladi, getattr asosida emas — shuning uchun nomni
actionsdan izohga olib tashlash uni shunchaki yashirish emas, balki
butunlay o‘chirib qo‘yadi.
O‘rnatilgan delete amali
"delete" tasdiqlash sahifasida ko‘rsatilgan xuddi shu o‘chirish rejasini
bajaradi va yozishdan oldin uni yana bir bor tekshiradi — chunki sahifa bir
soatdan beri ochiq turgan bo‘lishi va shu vaqt ichida bog‘lanishlar grafi
o‘zgargan bo‘lishi mumkin.
Tanlangan qatorlardan birortasi himoyalangan bo‘lsa, hech narsa o‘chirilmaydi va sahifa qaysi qator ekanini ko‘rsatadi.
Xatolar
Istisno tashlang — va hammasi orqaga qaytariladi, operatorga esa xabar ko‘rsatiladi:
from fastfort import ValidationError
@admin.action("Ship", icon="truck")
async def ship(self, adapter, objects):
unpaid = [s for s in objects if s.customer and not s.customer.is_active]
if unpaid:
raise ValidationError(
f"{len(unpaid)} shipments belong to inactive customers.",
hint="Reactivate the customer, or deselect those rows.",
)
...
ValidationError sahifada xabar sifatida ko‘rsatiladi. Boshqa har qanday
narsa, ishlab chiqarish muhitida, umumiy xatolikka aylanadi — trassirovka
kimningdir ekranida emas, sizning loglaringizda bo‘ladi.