Foydalanuvchilarga aktual promo kodlarni Web sayt va Telegram bot orqali taqdim etuvchi tizim. Backend va bot bitta umumiy PostgreSQL ma'lumotlar bazasi va Django REST API orqali ishlaydi.
- Arxitektura
- Texnologiyalar
- Loyiha tuzilishi
- O'rnatish (Backend)
- O'rnatish (Telegram bot)
- Muhit o'zgaruvchilari (.env)
- API hujjatlari (Swagger)
- Admin panel
- Testlash
- Ma'lumotlar bazasi sxemasi
- Muammolarni bartaraf etish
┌──────────────────┐
│ PostgreSQL DB │
└────────┬─────────┘
│
┌────────┴─────────┐
│ Django + DRF │
│ (REST API + │
│ Admin panel) │
└────────┬─────────┘
│ HTTP (JSON)
┌────────────┴────────────┐
│ │
┌────────┴────────┐ ┌─────────┴────────┐
│ Web Frontend │ │ Telegram Bot │
│ (kelajakda) │ │ (Aiogram 3) │
└──────────────────┘ └──────────────────┘
Backend va bot bir xil ma'lumotlar bazasiga bevosita emas, balki bitta umumiy REST API orqali ulanadi. Bot hech qachon PostgreSQL bilan to'g'ridan-to'g'ri ishlamaydi — bu barcha biznes-logikani (aktiv/muddati o'tgan promo kodlarni filtrlash va h.k.) bitta joyda saqlashni ta'minlaydi.
Yozish (Create/Update/Delete) operatsiyalari faqat Django admin panel orqali amalga oshiriladi. Ochiq API faqat o'qish (read-only) uchun mo'ljallangan — login/logout kerak emas.
| Qatlam | Texnologiya |
|---|---|
| Backend / API | Django 5 + Django REST Framework |
| Ma'lumotlar bazasi | PostgreSQL |
| API hujjatlari | drf-spectacular (Swagger UI) |
| Filtrlash | django-filter |
| Telegram bot | Python 3 + Aiogram 3 (async) |
| HTTP client (bot → API) | httpx |
| Testlash (backend) | pytest, pytest-django, model-bakery |
| Testlash (bot) | pytest, pytest-asyncio |
promo-code-system/
├── venv/ # Django uchun virtual muhit
├── manage.py
├── requirements.txt
├── .env # Django uchun maxfiy sozlamalar (Git'ga qo'shilmaydi)
├── config/ # Django loyiha sozlamalari
│ ├── settings.py
│ ├── urls.py
│ └── ...
├── categories/ # Kategoriyalar ilovasi
│ ├── models.py
│ ├── serializers.py
│ ├── views.py
│ ├── admin.py
│ ├── urls.py
│ └── tests/
├── brands/ # Brendlar + Brend slayderlari ilovasi
│ ├── models.py
│ ├── serializers.py
│ ├── views.py
│ ├── admin.py
│ ├── urls.py
│ └── tests/
├── promos/ # Promo kodlar ilovasi
│ ├── models.py
│ ├── serializers.py
│ ├── views.py
│ ├── admin.py
│ ├── urls.py
│ └── tests/
├── core/ # Umumiy/yordamchi kod
└── bot/ # Telegram bot (alohida servis)
├── venv/ # Bot uchun alohida virtual muhit
├── .env # Bot uchun maxfiy sozlamalar (Git'ga qo'shilmaydi)
├── main.py # Kirish nuqtasi
├── config.py
├── api_client.py # Django API bilan ishlash uchun yagona qatlam
├── keyboards/
│ ├── __init__.py # CallbackData sxemasi
│ └── inline.py # Inline tugmalar
├── handlers/
│ ├── start.py
│ ├── categories.py
│ ├── brands.py
│ └── promos.py
└── tests/
git clone <repo-url>
cd promo-code-systempython -m venv venv
# Windows
venv\Scripts\activate
# macOS / Linux
source venv/bin/activatepip install -r requirements.txtpsql -U postgresCREATE DATABASE promo_db;
GRANT ALL PRIVILEGES ON DATABASE promo_db TO postgres;
GRANT ALL ON SCHEMA public TO postgres;
ALTER DATABASE promo_db OWNER TO postgres;
\qPostgreSQL 15+ da
publicsxemasiga yozish huquqi standart bo'yicha berilmaydi — shuning uchun yuqoridagiGRANT/ALTERbuyruqlari zarur.
Loyiha ildizida (manage.py bilan bir joyda) .env faylini yarating — namuna uchun Muhit o'zgaruvchilari bo'limiga qarang.
python manage.py migratepython manage.py createsuperuserTerminal so'raydi:
- Username — masalan,
admin - Email — ixtiyoriy
- Password — ikki marta kiritiladi (belgilar ko'rinmaydi, bu normal holat)
python manage.py runserverBackend manzili: http://127.0.0.1:8000/
Bot alohida Python muhitda ishlaydi, backenddan mustaqil ravishda ishga tushiriladi.
cd bot
python -m venv venv
# Windows
venv\Scripts\activate
# macOS / Linux
source venv/bin/activatepip install -r requirements.txt- Telegramda @BotFather botiga o'ting
/newbotbuyrug'ini yuboring va ko'rsatmalarga amal qiling- Bergan tokenni saqlab qo'ying
Namuna uchun Muhit o'zgaruvchilari bo'limiga qarang.
Muhim: Django backend server (
python manage.py runserver) alohida terminalda ishlab turgan bo'lishi shart — bot API orqali ma'lumot oladi.
python main.pyTelegramda botingizni topib, /start buyrug'ini yuboring.
SECRET_KEY=django-insecure-change-this-in-production
DEBUG=True
DB_NAME=promo_db
DB_USER=postgres
DB_PASSWORD=your_password
DB_HOST=localhost
DB_PORT=5432BOT_TOKEN=your_bot_token_from_botfather
API_BASE_URL=http://127.0.0.1:8000/apiProductionga chiqarganda
API_BASE_URLni haqiqiy domenga o'zgartiring, masalan:https://api.promokod.uz/api
Diqqat: .env fayllari .gitignore orqali repozitoriyga yuklanmaydi. Har bir muhitda (lokal, server) bu fayllarni qo'lda yaratish kerak.
Backend server ishga tushgandan so'ng, to'liq interaktiv API hujjatlari quyidagi manzilda mavjud:
http://127.0.0.1:8000/api/docs/
Bu yerda barcha endpointlarni ko'rish va to'g'ridan-to'g'ri brauzerdan "Try it out" orqali sinab ko'rish mumkin. Hujjatlar avtomatik ravishda serializer va view'lardan generatsiya qilinadi — har doim kodga mos keladi.
| Endpoint | Metod | Tavsif |
|---|---|---|
/api/categories/ |
GET | Barcha kategoriyalar ro'yxati |
/api/categories/{id}/ |
GET | Bitta kategoriya haqida ma'lumot |
/api/brands/ |
GET | Barcha brendlar ro'yxati |
/api/brands/{id}/ |
GET | Brend + uning slayder rasmlari |
/api/brands/sliders/ |
GET | Barcha brend slayderlari |
/api/promos/ |
GET | Aktiv promo kodlar ro'yxati (code maydonisiz) |
/api/promos/{id}/ |
GET | Promo kod to'liq ma'lumoti (code bilan) |
/api/promos/?category={id} |
GET | Kategoriya bo'yicha filtrlash |
/api/promos/?brand={id} |
GET | Brend bo'yicha filtrlash |
/api/promos/?search={text} |
GET | Sarlavha/tavsif bo'yicha qidiruv |
API faqat read-only (GET). Barcha yaratish/o'zgartirish/o'chirish amallari faqat Django admin panel orqali bajariladi.
Barcha CRUD amallari (Categories, Brands, Brand Sliders, Promo Codes) uchun:
http://127.0.0.1:8000/admin/
Kirish uchun createsuperuser orqali yaratilgan login/parol ishlatiladi.
Imkoniyatlar:
- Promo kodlarni
is_activeorqali tez yoqish/o'chirish (ro'yxatdan to'g'ridan-to'g'ri) - Brend qo'shishda uning slayder rasmlarini bir joyda (inline) qo'shish
- Kategoriya, brend va sarlavha bo'yicha qidiruv/filtrlash
cd promo-code-system
venv\Scripts\activate
pytestCoverage hisoboti bilan:
pytest --cov=categories --cov=brands --cov=promos --cov-report=term-missingcd bot
venv\Scripts\activate
pytest| Jadval | Asosiy maydonlar |
|---|---|
categories |
id, name, image, created_at |
brand |
id, name, image, created_at |
brend_slider |
id, brand_id (FK), image, position |
promo_codes |
id, title, code (unique), description, image, url, brand_id (FK), category_id (FK), expires_at, is_active, created_at, updated_at |
brand_idvacategory_id—PROTECTrejimida, ya'ni ular bilan bog'liq promo kodlar mavjud bo'lsa, brend/kategoriyani o'chirib bo'lmaydi.PromoCode.is_visible—is_active=Truevaexpires_atmuddati o'tmagan bo'lsa,Trueqaytaradi. Ochiq API va bot faqat shu shartga mos promo kodlarni ko'rsatadi.
permission denied for schema public — PostgreSQL 15+ da schema huquqlarini qo'lda berish kerak, 4-qadamga qarang.
Swagger /api/docs/ ishlamayapti / 500 xato — drf_spectacular INSTALLED_APPS va REST_FRAMEWORK['DEFAULT_SCHEMA_CLASS'] sozlamalarida borligini tekshiring.
Bot rasm yubora olmayapti (wrong type of the web page content) — bot va backend bir xil (lokal) mashinada ishlayotgan bo'lsa, answer_photoga to'g'ridan-to'g'ri 127.0.0.1 URL berib bo'lmaydi, chunki Telegram serverlari uni tushunmaydi. bot/handlers/promos.py ichida rasm avval httpx orqali yuklab olinib, so'ng BufferedInputFile sifatida yuboriladi — bu productionda (haqiqiy domen bilan) kerak emas, lekin lokal testda zarur.
there is no text in the message to edit — foydalanuvchi rasmli xabardan matnli xabarga o'tayotganda yuz beradi. Barcha edit_text chaqiruvlari try/except bilan o'ralgan bo'lishi va xato bo'lsa xabarni o'chirib, yangisini yuborishi kerak (handlers/ papkasidagi barcha fayllarda qo'llanilgan).
ModuleNotFoundError / bo'sh urls.py — har bir ilova (categories, brands, promos) o'zining urls.py fayliga ega bo'lishi va u DRF router orqali to'g'ri sozlangan bo'lishi kerak.
Ushbu loyiha shaxsiy/bitiruv loyihasi sifatida ishlab chiqilgan.