Filtrlar va qidiruv

Bitta kortej, oltita boshqaruv shakli — va FastFort filtrlashdan bosh tortadigan ikki xil maydon, sababi bilan birga.

Mavjud v0.1.0

Siz hech qachon filtr uchun boshqaruv elementini ko‘rsatmaysiz. list_filter ustunlarni nomlaydi; boshqaruv elementini ustunning o‘z turi tanlaydi.

class ProductAdmin(admin.ModelAdmin):
    list_filter = ("availability", "is_active", "category", "supplier",
                   "price", "released_on")

Har bir tur nimani hosil qiladi

Ustun turiBoshqaruv elementi
EnumUstunning o‘z qiymatlaridan tuzilgan ochiladigan ro‘yxat
BooleanUchta holat: har qanday, ha, yo‘q — hech qachon checkbox emas
Nullable booleanTo‘rtta holat, chunki «belgilanmagan» ham alohida javob
Tashqi kalit · birma-birTanlagich; nishon jadval ochiladigan ro‘yxatga sig‘masa, avtomatik to‘ldirish bilan
Integer · float · decimal · moneyIkkita chegara, dan va gacha, ikkalasi ham ixtiyoriy
Date · datetimeTayyor variantli diapazon — bugun, oxirgi 7 kun, shu oy
Time · durationXuddi shu ikki chegarali shakl, ustunning o‘z birliklarida
UUIDAniq mos kelish

Ikki bosh tortish

Ikki xil maydon bo‘yicha filtrlash mumkin emas, va bu bosh tortish sahifada emas, ModelAdmin qurilayotganda sodir bo‘ladi:

ConfigurationError: SupplierAdmin is misconfigured:
  - list_filter names 'country'; free-text and multi-valued fields
    cannot be offered as a filter

Erkin matn

String yoki Text ustuni. Uning ochiladigan ro‘yxati jadvaldagi har bir noyob qiymatdan iborat bo‘lardi — customers.name uchun bu har bir mijoz uchun bittadan variant bo‘ladi va har sahifa yuklanganda qayta so‘raladi.

Bu filtrlanadigandek ko‘ringan narsalarni ham ushlab qoladi. String(2) mamlakat kodi sizning boshingizda yopiq to‘plam, lekin ustun nuqtai nazaridan — oddiy erkin matn:

country: Mapped[str] = mapped_column(sa.String(2), default="UZ")   # not filterable

Yechim — to‘plamni aniq ko‘rsatish, shundan so‘ng u filtrlana boshlaydi:

class Country(enum.StrEnum):
    UZ = "UZ"
    KZ = "KZ"
    TR = "TR"

country: Mapped[Country] = mapped_column(sa.Enum(Country, name="country"))

Ko‘pdan-ko‘pga

Ko‘p qiymatli maydon, shu sababli filtr bilan solishtiriladigan yagona qiymat yo‘q. Mahsulotdagi tags — ro‘yxat; «tegi bestseller bo‘lgan mahsulotlar» degan savol biror yoki barcha degani nazarda tutilishi hal qilinmaguncha to‘g‘ri qo‘yilmagan bo‘ladi.

Ikkalasi ham qidiriladigan, saralanadigan va ko‘rsatiladigan bo‘lib qoladi. Faqat filtr paneli ular uchun yopiq.

Qidiruv maydoni

search_fields = ("id", "sku", "name", "description")

search_fields bo‘lmasa, qidiruv maydoni umuman chizilmaydi — bu hech narsani jimgina topmaydigan maydondan yaxshiroq.

Ikki xil ustun mos keladi, va ular har xil usulda solishtiriladi.

Matn qism satr bo‘yicha solishtiriladi, katta-kichik harflarga farqsiz, har qanday bazada: STRING, TEXT, EMAIL, URL. INET matnga o‘xshab ko‘rinsa-da, atayin chiqarib tashlangan, chunki PostgreSQL’da inet uchun LIKE yo‘q — bunday ustun ustida icontains operator does not exist xatosi bilan qulaydi, 500 xato qaytaradigan qidiruv maydoni esa ustunni shunchaki o‘tkazib yuboradigan maydondan yomonroq.

ID’lar aniq mos kelish bo‘yicha solishtiriladi: INTEGER, BIGINT va UUID. Bu odamlar admin qidiruv maydoniga haqiqatan ham nima yozishini aks ettiradi — id qo‘llab-quvvatlash so‘rovnomasi, hisob-faktura yoki log satridan keladi — va search_fields = ("id", "name") avval o‘zi ko‘ringandek ravshan qator emas, konfiguratsiya xatosi hisoblangan.

Qism satr emas, aynan aniq mos kelish — ikki sababga ko‘ra. 1 ni qidirish 1-qatorni qaytarishi kerak, 1, 12, 21 va 100-qatorlarni emas; va tenglik birlamchi kalit indeksidan foydalanadi, bigint’ni matnga aylantirib ustida LIKE '%1%' ishga tushirish esa id ustuni eng yaxshi indeks bo‘lgan jadvalni to‘liq skanerlash demakdir.

Ustun turiga umuman mos kelmaydigan qidiruv so‘zi so‘rovning shu yarmidan shunchaki tashlab yuboriladi. ("id", "name") bo‘yicha pixel ni qidirish faqat name bo‘yicha qidiradi; 42 ni qidirish esa ikkalasi bo‘yicha ham. id yagona qidiruv maydoni bo‘lganda so‘z qidirish hech narsa qaytarmaydi — bu to‘g‘ri javob, hammasini qaytarish bilan bir xil emas.

Qolgan hamma narsa hali ham qurilish bosqichidagi xato, sababi bilan birga:

- search_fields names 'price', which is a decimal column. Search matches
  text fields by substring and integer and UUID fields exactly; there is
  no useful reading of a search term for this one. Offer it through
  list_filter instead.

Bog‘lanishlar bo‘yicha yo‘lni ko‘rsatib, ularning o‘z ustunlari orqali qidiriladi:

search_fields = ("id", "name", "category__name")

URL orqali filtrlash

ListQuery.from_params — xom so‘rov satridagi kirish so‘rovga aylantiriladigan yagona joy. Saralash kalitlari, filtr maydonlari va operatorlar spesifikatsiyadan olingan ruxsat etilganlar ro‘yxati bo‘yicha tekshiriladi; keyingi bosqichlarning birortasi ham qayta tekshirmaydi, chunki bunga ehtiyoj yo‘q.

?availability=in_stock                 exact
?price__gte=50000&price__lte=200000    a range
?released_on__range=2026-01-01,2026-06-30
?category__isnull=true
?q=cable                               the search box
?o=-created_at                         ordering
?ps=100                                page size, capped at admin.max_page_size

Mavjud operatorlar: exact, iexact, ne, lt, lte, gt, gte, in, isnull, range, icontains, istartswith, iendswith.

Shu maydon uchun ruxsat etilganlar ro‘yxatida bo‘lmagan har qanday narsa o‘tkazilmay, rad etiladi — admin taklif qilmagan ustun bo‘yicha filtrga manzil satriga yozib ham yetib bo‘lmaydi.

Saqlangan ko‘rinishlar

Filtr — bu so‘rov satri bo‘lgani uchun, u allaqachon ulashish mumkin — URL’ni nusxalab, yuboring. Yetishmayotgan narsa — qaytib kelishga arziydigan narsaga nom berish edi.

Filtr tugmasi yonidagi Ko‘rinishlar menyusi nomlangan URL manzillar to‘plamini butunlay brauzerda saqlaydi: serverda hech narsa yozilmaydi, chunki so‘rov satri allaqachon haqiqat manbai bo‘lgan, va uning ikkinchi nusxasi faqat ikkalasi kelishmay qolishi mumkin bo‘lgan yana bir joy bo‘lardi. Saqlangan ko‘rinishga qaytish har doim birinchi sahifadan boshlanadi — sahifa raqami hech qachon ko‘rinish nimani anglatishining bir qismi bo‘lmagan.

Buning uchun hech qanday ModelAdmin opsiyasi kerak emas — kerak ham emas. Loyihaning o‘z ModelAdmini allaqachon chizayotgan har qanday ro‘yxat Ko‘rinishlar menyusini bepul oladi, xuddi Export’ni olganidek.

Ustunlar ko‘rinishi

Keng model har bir ustun uchun har bir qatorda to‘lov oladi — bu ekranni o‘qiyotgan kishiga u ustun kerakmi yoki yo‘qmi, farqi yo‘q. Ustunlar menyusi — har bir ko‘rsatilgan ustun uchun bitta tugma — kerak bo‘lmagan kenglikni yashiradi, va buni har bir ro‘yxat uchun, har bir brauzerda, localStorageda eslab qoladi.

Bu ko‘rinish sozlamasi, so‘rov emas: yashirin ustun baribir so‘raladi va baribir eksport qilish mumkin, faqat chizilmaydi. Bu yerda ham hech qanday ModelAdmin konfiguratsiyasi kerak emas — Saqlangan ko‘rinishlar bilan bir xil sababga ko‘ra: u allaqachon har bir ro‘yxatda mavjud.

Fazoviy filtrlar

Geometriya yoki geografiya ustunida:

?catchment__within=POLYGON((...))
?catchment__intersects=POINT(69.28 41.31)
?last_seen__dwithin=41.3111,69.2797,5000
?catchment__bbox=69.1,41.2,69.4,41.4

Shuningdek contains, overlaps, touches, crosses.

dwithin bilan ehtiyot bo‘lish kerak, va FastFort buni siz uchun qiladi: uchinchi son geography ustunida metr, geometryda esa SRID birliklari — 4326 uchun gradus. Spesifikatsiya aynan shu ikkisi aralashib ketmasligi uchun geography bayrog‘ini olib yuradi, so‘rov esa kerak bo‘lgan joyda turni o‘zgartiradi.

Vektorli qidiruv

pgvector ustunida:

?embedding__near=[0.4,0.1,0.9]&embedding__k=5

Eng yaqinidan boshlab saralaydi, va bu tartib sahifadan so‘ralgan boshqa har qanday narsadan ustun turadi — alifbo bo‘yicha emas, «eng yaqini, tenglik bo‘lsa nom bo‘yicha» tartibida.

cosine (standart), l2, l1 va inner masofa operatorini tanlaydi, chegara ham mavjud:

?embedding__near=[0.4,0.1,0.9]&embedding__metric=l2&embedding__within=0.35