Metadata-Version: 2.4
Name: proweb
Version: 0.1.0
Summary: O'zbekcha to'liq asinxron web framework - FastAPI + Tortoise ORM + Flask-style
Home-page: https://github.com/proweb/proweb
Author: ProWeb Team
Author-email: info@proweb.uz
Project-URL: Documentation, https://proweb.uz/docs
Project-URL: Source, https://github.com/proweb/proweb
Project-URL: Bug Reports, https://github.com/proweb/proweb/issues
Keywords: web framework fastapi tortoise-orm async uzbek o'zbek asinxron
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: fastapi>=0.104.0
Requires-Dist: uvicorn[standard]>=0.24.0
Requires-Dist: tortoise-orm>=0.20.0
Requires-Dist: aerich>=0.7.2
Requires-Dist: jinja2>=3.1.2
Requires-Dist: python-multipart>=0.0.6
Requires-Dist: click>=8.1.7
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pydantic-settings>=2.0.0
Provides-Extra: postgresql
Requires-Dist: asyncpg>=0.28.0; extra == "postgresql"
Provides-Extra: mysql
Requires-Dist: aiomysql>=0.2.0; extra == "mysql"
Provides-Extra: dev
Requires-Dist: pytest>=7.4.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: black>=23.7.0; extra == "dev"
Requires-Dist: flake8>=6.1.0; extra == "dev"
Requires-Dist: mypy>=1.5.0; extra == "dev"
Dynamic: author
Dynamic: author-email
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: project-url
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# 🚀 ProWeb - O'zbekcha To'liq Asinxron Web Framework

**ProWeb** - bu FastAPI, Tortoise ORM va Flask-style kodlash usulini birlashtirgan, to'liq o'zbekcha dokumentatsiyali, zamonaviy asinxron web framework.

## ✨ Asosiy Xususiyatlar

- 🔥 **FastAPI asosida** - yuqori tezlikda ishlovchi API
- 🐢 **Tortoise ORM** - to'liq asinxron ORM (Django-style)
- 🌶️ **Flask-style kodlash** - oddiy va tushunarli sintaksis
- 🎨 **Jinja2 templates** - osonlashtirilgan shablonlar
- 🛠️ **Avtomatik Admin Panel** - Django kabi tayyor admin
- 📦 **Django-style CLI** - tanish komandalar
- 🇺🇿 **O'zbekcha dokumentatsiya** - to'liq o'zbek tilida
- ⚡ **100% Asinxron** - barcha operatsiyalar async/await

## 📥 O'rnatish

```bash
pip install proweb
```

Yoki GitHub'dan:

```bash
git clone https://github.com/proweb/proweb.git
cd proweb
pip install -e .
```

## 🎯 Tezkor Boshlash

### 1. Yangi loyiha yaratish

```bash
proweb createproject mening_saytim
cd mening_saytim
pip install -r requirements.txt
```

### 2. Yangi ilova yaratish

```bash
proweb createapp blog
```

### 3. Model yaratish

`apps/blog/models.py`:

```python
from proweb import Model, fields

class Maqola(Model):
    sarlavha = fields.CharField(max_length=200)
    matn = fields.TextField()
    muallif = fields.CharField(max_length=100)
    yaratilgan = fields.DatetimeField(auto_now_add=True)
    
    class Meta:
        table = "maqolalar"
    
    def __str__(self):
        return self.sarlavha
```

### 4. Migratsiya qilish

```bash
proweb makemigrations
proweb migrate
```

### 5. View yaratish

`apps/blog/views.py`:

```python
from proweb import ProWeb
from proweb.templates import render_template
from .models import Maqola

async def maqolalar_royxati():
    """Barcha maqolalar ro'yxati"""
    maqolalar = await Maqola.barchasini_olish()
    return await render_template(
        "blog/list.html",
        maqolalar=maqolalar
    )

async def maqola_detali(id: int):
    """Bitta maqola batafsil"""
    maqola = await Maqola.olish(id=id)
    return await render_template(
        "blog/detail.html",
        maqola=maqola
    )
```

### 6. URL routing

`main.py`:

```python
from proweb import ProWeb
from apps.blog import views

app = ProWeb(__name__)

# Flask-style routing
@app.get("/")
async def bosh_sahifa():
    return {"xabar": "Salom Dunyo!"}

@app.get("/maqolalar")
async def maqolalar():
    return await views.maqolalar_royxati()

@app.get("/maqolalar/{id}")
async def maqola_detali(id: int):
    return await views.maqola_detali(id)

# API endpoint
@app.post("/api/maqola/")
async def maqola_yaratish(sarlavha: str, matn: str):
    maqola = await Maqola.yaratish(
        sarlavha=sarlavha,
        matn=matn
    )
    return {"id": maqola.id, "xabar": "Muvaffaqiyatli yaratildi"}
```

### 7. Admin panel sozlash

`apps/blog/admin.py`:

```python
from proweb.admin import admin_site, ModelAdmin
from .models import Maqola

class MaqolaAdmin(ModelAdmin):
    list_display = ['id', 'sarlavha', 'muallif', 'yaratilgan']
    search_fields = ['sarlavha', 'matn']
    list_filter = ['yaratilgan']

admin_site.register(Maqola, MaqolaAdmin)
```

### 8. Serverni ishga tushirish

```bash
proweb runserver
```

Endi quyidagi manzillar ochiladi:
- 🌐 Veb sayt: http://127.0.0.1:8000
- 🛠️ Admin panel: http://127.0.0.1:8000/admin
- 📚 API Docs: http://127.0.0.1:8000/docs

## 📚 To'liq Misol

### Complete CRUD misol

```python
from proweb import ProWeb, Model, fields
from proweb.templates import render_template
from fastapi import HTTPException

app = ProWeb(__name__)

# Model
class Kitob(Model):
    nomi = fields.CharField(max_length=200)
    muallif = fields.CharField(max_length=100)
    narx = fields.DecimalField(max_digits=10, decimal_places=2)
    nashr_yili = fields.IntField()
    
    class Meta:
        table = "kitoblar"
    
    def __str__(self):
        return f"{self.nomi} - {self.muallif}"

# Views
@app.get("/kitoblar")
async def kitoblar_royxati():
    """Barcha kitoblar"""
    kitoblar = await Kitob.all()
    return await render_template("kitoblar/list.html", kitoblar=kitoblar)

@app.get("/kitoblar/{id}")
async def kitob_detali(id: int):
    """Bitta kitob"""
    kitob = await Kitob.get_or_none(id=id)
    if not kitob:
        raise HTTPException(status_code=404, detail="Kitob topilmadi")
    return await render_template("kitoblar/detail.html", kitob=kitob)

@app.post("/api/kitoblar/")
async def kitob_yaratish(
    nomi: str,
    muallif: str,
    narx: float,
    nashr_yili: int
):
    """Yangi kitob yaratish"""
    kitob = await Kitob.create(
        nomi=nomi,
        muallif=muallif,
        narx=narx,
        nashr_yili=nashr_yili
    )
    return {"id": kitob.id, "xabar": "Kitob qo'shildi"}

@app.put("/api/kitoblar/{id}")
async def kitob_yangilash(
    id: int,
    nomi: str = None,
    narx: float = None
):
    """Kitobni yangilash"""
    kitob = await Kitob.get(id=id)
    if nomi:
        kitob.nomi = nomi
    if narx:
        kitob.narx = narx
    await kitob.save()
    return {"xabar": "Yangilandi"}

@app.delete("/api/kitoblar/{id}")
async def kitob_ochirish(id: int):
    """Kitobni o'chirish"""
    kitob = await Kitob.get(id=id)
    await kitob.delete()
    return {"xabar": "O'chirildi"}
```

## 🎨 Template misoli

`templates/kitoblar/list.html`:

```html
<!DOCTYPE html>
<html lang="uz">
<head>
    <meta charset="UTF-8">
    <title>Kitoblar ro'yxati</title>
    <link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
    <h1>Kitoblar</h1>
    
    {% for kitob in kitoblar %}
    <div class="kitob-karta">
        <h2>{{ kitob.nomi }}</h2>
        <p>Muallif: {{ kitob.muallif }}</p>
        <p>Narx: {{ kitob.narx|raqam_formati }} so'm</p>
        <p>Yil: {{ kitob.nashr_yili }}</p>
        <a href="/kitoblar/{{ kitob.id }}">Batafsil</a>
    </div>
    {% endfor %}
</body>
</html>
```

## 🛠️ CLI Komandalar

```bash
# Loyiha yaratish
proweb createproject loyiha_nomi

# Ilova yaratish
proweb createapp app_nomi

# Migratsiyalar
proweb makemigrations
proweb migrate

# Server ishga tushirish
proweb runserver
proweb runserver --host 0.0.0.0 --port 8080

# Superuser yaratish
proweb createsuperuser

# Python shell
proweb shell
```

## 🔧 Sozlamalar

`settings.py`:

```python
# Ma'lumotlar bazasi
DATABASE_URL = "sqlite://db.sqlite3"
# DATABASE_URL = "postgres://user:pass@localhost:5432/mydb"
# DATABASE_URL = "mysql://user:pass@localhost:3306/mydb"

# Debug
DEBUG = True

# Secret key
SECRET_KEY = "maxfiy-kalit"

# Ilovalar
INSTALLED_APPS = [
    "proweb.contrib.admin",
    "proweb.contrib.auth",
    "apps.blog",
    "apps.shop",
]

# ORM modellar
MODELS_MODULES = ["apps.blog.models", "apps.shop.models"]

# Templates
TEMPLATES_DIR = "templates"

# Static fayllar
STATIC_DIR = "static"
STATIC_URL = "/static/"
```

## 📖 ORM Qo'llanma

### Model yaratish

```python
from proweb import Model, fields

class Foydalanuvchi(Model):
    ism = fields.CharField(max_length=100)
    email = fields.CharField(max_length=255, unique=True)
    yosh = fields.IntField()
    faol = fields.BooleanField(default=True)
    yaratilgan = fields.DatetimeField(auto_now_add=True)
    
    class Meta:
        table = "foydalanuvchilar"
```

### CRUD operatsiyalar

```python
# Yaratish
user = await Foydalanuvchi.create(
    ism="Ali",
    email="ali@example.com",
    yosh=25
)

# O'qish
user = await Foydalanuvchi.get(id=1)
users = await Foydalanuvchi.all()

# Filtrlash
faol_userlar = await Foydalanuvchi.filter(faol=True)
yosh_userlar = await Foydalanuvchi.filter(yosh__gte=18)

# Yangilash
user.ism = "Vali"
await user.save()

# O'chirish
await user.delete()
```

### Munosabatlar

```python
class Mualif(Model):
    ism = fields.CharField(max_length=100)

class Kitob(Model):
    nomi = fields.CharField(max_length=200)
    mualif = fields.ForeignKeyField(
        "models.Mualif",
        related_name="kitoblar"
    )

# Ishlatish
mualif = await Mualif.create(ism="O'tkir Hoshimov")
kitob = await Kitob.create(
    nomi="Ikki eshik orasi",
    mualif=mualif
)

# Related objects
kitoblar = await mualif.kitoblar.all()
```

## 🎯 Best Practices

### 1. Asinxron funksiyalardan foydalaning

```python
@app.get("/users")
async def get_users():
    # ✅ To'g'ri - asinxron
    users = await User.all()
    return users

# ❌ Noto'g'ri - sinxron
def get_users_sync():
    users = User.all()  # Bu ishlamaydi!
    return users
```

### 2. Try-except ishlatish

```python
@app.get("/user/{id}")
async def get_user(id: int):
    try:
        user = await User.get(id=id)
        return user
    except DoesNotExist:
        raise HTTPException(status_code=404, detail="User topilmadi")
```

### 3. Validatsiya

```python
from pydantic import BaseModel, EmailStr

class UserCreate(BaseModel):
    ism: str
    email: EmailStr
    yosh: int

@app.post("/users/")
async def create_user(data: UserCreate):
    user = await User.create(**data.dict())
    return user
```

## 🤝 Hissa qo'shish

Loyihaga hissa qo'shmoqchimisiz? Juda zo'r!

1. Repository ni fork qiling
2. Feature branch yarating (`git checkout -b yangi-xususiyat`)
3. O'zgarishlaringizni commit qiling
4. Branch'ni push qiling
5. Pull Request oching

## 📝 Litsenziya

MIT License - batafsil [LICENSE](LICENSE) faylida

## 🌟 Muallif

ProWeb Team - O'zbekiston

## 📞 Aloqa

- 🌐 Website: https://proweb.uz
- 📧 Email: info@proweb.uz
- 💬 Telegram: @proweb_uz
- 🐙 GitHub: https://github.com/proweb/proweb

---

⭐ Agar loyiha yoqsa, GitHub'da yulduzcha qo'yishni unutmang!
