Maydonlar va vidjetlar
FastFort taniydigan har bir ustun turi, u chizadigan boshqaruv elementi va oddiy boshqaruv elementini chizish ma’lumotlaringizni buzib qo‘yadigan to‘rtta holat.
Mavjud v0.1.0
Boshqaruv elementini siz tanlamaysiz — buni ustun turi hal qiladi. O‘ttiz yetti xil maydon turi yigirma bitta boshqaruv elementiga mos keladi, va bu moslik — bitta jadval, har bir shablondagi shart-sharoit emas.
Moslik jadvali
| Tur | Boshqaruv elementi | |
|---|---|---|
STRING | text | |
TEXT | textarea | |
INTEGER · BIGINT · FLOAT | number | Chegaralar ustundan olinadi |
DECIMAL | decimal | Aniqlik va masshtab ustundan olinadi |
MONEY | money | |
BOOLEAN | checkbox | …NULL qabul qiladigan holatlar bundan mustasno — pastga qarang |
DATE | date | Kalendar, uchta ko‘rinish |
DATETIME | datetime | Kalendar va chizilgan soat |
TIME | time | |
DURATION | duration | To‘rtta belgilangan raqam maydoni |
UUID | text | |
JSON | json | Noto‘g‘ri JSON’ni yubormaydi |
HSTORE | keyvalue | Har bir qatorda bitta key: value juftligi |
ENUM | select | A’zolar ustundan o‘qib olinadi |
EMAIL · URL | email · url | |
PASSWORD | password | Yangi parol va uni tasdiqlash |
FILE · IMAGE | file · image | Yuklash kartochkasi, drag-and-drop |
ARRAY | tags | Har bir element element turi bo‘yicha tekshiriladi |
RANGE · MULTIRANGE | range | Ikkita maydon va chegaralar tanlagichi |
INET | inet | Host yoki tarmoqni qabul qiladi |
MACADDR | mac | |
BITS | bits | Faqat 0 va 1 |
GEOMETRY | geometry | Matn maydoni va xarita |
VECTOR | textarea | Amalda faqat o‘qish uchun |
BINARY · SEARCH_VECTOR | readonly | Ko‘rsatiladi, lekin hech qachon yozilmaydi |
FOREIGN_KEY · ONE_TO_ONE | relation | Qidiruvli tanlagich |
MANY_TO_MANY | relations | O‘chiriladigan chiplar |
UNKNOWN | readonly | Faqat o‘qish uchun qator, buzilgan sahifa emas |
Ahamiyatli to‘rtta holat
Bu — oddiy boshqaruv elementini chizish ma’lumot yo‘qotilishiga olib keladigan holatlar.
NULL qabul qiluvchi mantiqiy (boolean) maydon — checkbox emas
Checkbox’da ikkita holat bor, ustunda esa — uchta. Uni checkbox sifatida
chizsak, kimdir formani ochib «Saqlash»ni bosgan zahoti NULL Falsega
aylanadi — bu hech kim so‘ramagan, sezilmagan ma’lumot o‘zgarishi.
two_factor_enabled: Mapped[bool | None] = mapped_column(default=None)
Uch holatli boshqaruv elementini oladi. «Belgilanmagan» — belgilanmagan bo‘lib qoladi.
Interval — matn maydoni emas
planned_duration: Mapped[dt.timedelta | None] = mapped_column(sa.Interval())
To‘rtta belgilangan maydon — kun, soat, daqiqa, soniya. 2 08:30:00 kabi
formatni kutuvchi matn maydoni — bu kimgadir tushuntirib berish kerak
bo‘lgan va baribir xato kiritiladigan format.
Uning ostidagi format bo‘yicha maslahat faqat skript ishlaganda
ko‘rsatiladi, chunki skript maydonni to‘rtta belgilangan kiritish maydoniga
almashtirgach, HH:MM:SS kabi yozish haqidagi ko‘rsatma allaqachon sahifada
mavjud bo‘lmagan boshqaruv elementiga tegishli bo‘lib qoladi.
Hstore — Python dict’ining repr’i emas
attributes: Mapped[dict[str, str] | None] = mapped_column(postgresql.HSTORE())
Har bir qatorda bitta key: value jufti. Ro‘yxat katagida bu juftliklar
shaklida ko‘rsatiladi, {'colour': 'black'} kabi emas — bu esa Python
dasturchisi bo‘lmagan har qanday kishiga buzilgan ma’lumotdek ko‘rinadi.
Range’ga qavslar shart emas
dock_numbers: Mapped[Any | None] = mapped_column(postgresql.INT4RANGE())
contract_period: Mapped[Any | None] = mapped_column(postgresql.DATERANGE())
Ikkita maydon va chegaralar tanlagichi. Chekka nuqtalar uchun xuddi shu
turdagi alohida ustun uchun ishlatiladigan boshqaruv elementlari jadvali
qo‘llaniladi — shuning uchun daterangening ikkala maydoni oddiy Date
ustuni oladigan xuddi shu kalendarni oladi, va ular bir-biridan chetlashib
keta olmaydi.
MULTIRANGE esa xuddi shu boshqaruv elementi ichida har bir qatorda bitta
range’ga siqiladi.
Bitta ustunni qayta belgilash
Ba’zi narsalarni ustunning o‘zi sizga aytib bera olmaydi. Yetti belgili satr faqat loyihangiz shunday deganligi uchun rang hisoblanadi.
class TagAdmin(admin.ModelAdmin):
formfield_overrides = {"colour": "color"}
class ProductAdmin(admin.ModelAdmin):
formfield_overrides = {
"image": "image", # a String holding a path
"datasheet": "file",
"description": "richtext",
}
Vidjet nomlari e’lon qilish bosqichida tekshiriladi. Xato yozilgan nom — mavjud barcha nomlar ro‘yxati bilan chiqadigan xatolik, jim-jit faqat o‘qish uchun ko‘rsatiladigan maydon emas.
Turni hamma joyda qayta belgilash
Agar loyihangizda yigirmata modelda ishlatiladigan EmailAddress turi
bo‘lsa, sizga email uchun boshqaruv elementi u ishlatilgan hamma joyda
kerak — kimdir esiga tushirgan ba’zi modellardagina emas. Bir marta
unutilgan formfield_overrides — bu hech kim ko‘rib chiqmagan sahifadagi
oddiy matn maydonidagi parol xeshi degani.
import sqlalchemy as sa
from fastfort.orm.sqlalchemy import Classification, register_type
from fastfort.spec import FieldType
class EmailAddress(sa.types.TypeDecorator[str]):
impl = sa.String
cache_ok = True
class PasswordHash(sa.types.TypeDecorator[str]):
impl = sa.String
cache_ok = True
_RULES = {EmailAddress: FieldType.EMAIL, PasswordHash: FieldType.PASSWORD}
def _classify(column):
for declared, field_type in _RULES.items():
if isinstance(column.type, declared):
return Classification(field_type)
# Decline, and the next rule gets a turn. Every rule follows this contract.
return None
def register_project_types() -> None:
register_type(_classify, first=True)
Ikkita narsani to‘g‘ri qilish kerak:
first=True. Busiz bu qoidalar hech qachon ishlamaydi — String
ustidagi TypeDecorator oxiriga qo‘shilgan qoidaga yetib borishdan ancha
oldin o‘rnatilgan String qoidasiga mos kelib qoladi, va ustun oddiy matn
sifatida tasniflanadi.
Buni biror narsa introspeksiya qilinishidan oldin chaqiring. Spesifikatsiyalar backend’da keshlanadi, shuning uchun qoida ro‘yxatdan o‘tkazilishidan oldin qurilgan spesifikatsiya noto‘g‘ri bo‘lib qolaveradi.
def build_fort() -> FastFort:
register_project_types() # first statement, not after
fort = FastFort(...)
Fayl yuklash
file va image — yo‘lni saqlaydigan oddiy satr (string) ustunlari.
Baytlar media.root ostiga tushadi; ustun esa yozilgan qiymatni saqlaydi.
Yuklash kartochkasi URL.createObjectURL orqali rasm yoki video preview’i
bilan drag-and-drop’ni qo‘llab-quvvatlaydi — va uning ichida haqiqatda
yuborishni bajaruvchi narsa sifatida original <input type="file">
saqlanib qoladi, shuning uchun JavaScript o‘chirilgan holda ham ishlayveradi.
Yuklangan fayllar boshqa har qanday view bilan bir xil to‘siq ortida, admin orqali taqdim etiladi. Yuklangan fayl — bu ommaviy resurs emas, boshqa har qanday qator kabi bir yozuv.
Ro‘yxat ustunida
list_displaydagi rasm ustuni saqlangan yo‘l o‘rniga eskiz (thumbnail)ni
ko‘rsatadi — chunki yo‘lga tasvirning o‘zi darhol javob beradi. Bu yerda hal
qiluvchi omil forma chizadigan boshqaruv elementi hisoblanadi, shuning
uchun formfield_overrides orqali rasm sifatida qayta belgilangan oddiy
String ham eskiz oladi:
class UserAdmin(admin.ModelAdmin):
list_display = ("id", "avatar", "email", "full_name")
formfield_overrides = {"avatar": "image"}
Hali surati bo‘lmagan qatorlar xuddi shunday o‘lchamdagi bo‘sh joy egallovchi (placeholder) oladi, shunda jadval notekis ko‘rinmaydi. Eskizlar lazy tarzda yuklanadi: yuz qatorli sahifa hali hech kim ularga aylantirmasdan turib yuzta so‘rov ochib yubormaydi.
Faqat o‘qish uchun bo‘lganlar
BINARY va SEARCH_VECTOR ko‘rsatiladi, lekin hech qachon yozilmaydi —
chunki rastr tasvir yoki to‘liq matnli indeksni kiritish mumkin bo‘lgan hech
qanday maydon yo‘q. UNKNOWN ham xuddi shunday: hech narsa tasniflay
olmaydigan ustun sahifani ag‘darib tashlash o‘rniga faqat o‘qish uchun
qatorga aylanadi.
Oxirgisi — orqasida test turgan hujjatlashtirilgan holat, chunki hech narsa sinamaydigan holat — bu haqiqiy loyiha unga birinchi marta yetib borganda buziladigan holatdir.