postgresdb3 0.7.0__tar.gz → 1.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. postgresdb3-1.0.1/PKG-INFO +302 -0
  2. postgresdb3-1.0.1/README.md +280 -0
  3. postgresdb3-1.0.1/postgresdb3/__init__.py +11 -0
  4. postgresdb3-1.0.1/postgresdb3/cli.py +62 -0
  5. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3/core/async_db.py +110 -15
  6. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3/core/sync_db.py +124 -37
  7. postgresdb3-1.0.1/postgresdb3/migrations/__init__.py +20 -0
  8. postgresdb3-1.0.1/postgresdb3/migrations/engine.py +241 -0
  9. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3/orm/base.py +9 -2
  10. postgresdb3-1.0.1/postgresdb3/orm/expressions.py +80 -0
  11. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3/orm/fields/__init__.py +2 -2
  12. postgresdb3-1.0.1/postgresdb3/orm/fields/datetime.py +32 -0
  13. postgresdb3-1.0.1/postgresdb3/orm/fields/foreign.py +61 -0
  14. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3/orm/fields/numeric.py +6 -0
  15. postgresdb3-1.0.1/postgresdb3/orm/meta.py +117 -0
  16. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3/orm/models.py +120 -43
  17. postgresdb3-1.0.1/postgresdb3/orm/query.py +696 -0
  18. postgresdb3-1.0.1/postgresdb3/orm/relations.py +196 -0
  19. postgresdb3-1.0.1/postgresdb3.egg-info/PKG-INFO +302 -0
  20. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3.egg-info/SOURCES.txt +4 -0
  21. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/setup.py +2 -2
  22. postgresdb3-0.7.0/PKG-INFO +0 -251
  23. postgresdb3-0.7.0/README.md +0 -229
  24. postgresdb3-0.7.0/postgresdb3/__init__.py +0 -1
  25. postgresdb3-0.7.0/postgresdb3/orm/fields/datetime.py +0 -17
  26. postgresdb3-0.7.0/postgresdb3/orm/fields/foreign.py +0 -31
  27. postgresdb3-0.7.0/postgresdb3/orm/meta.py +0 -61
  28. postgresdb3-0.7.0/postgresdb3/orm/query.py +0 -473
  29. postgresdb3-0.7.0/postgresdb3/orm/relations.py +0 -44
  30. postgresdb3-0.7.0/postgresdb3.egg-info/PKG-INFO +0 -251
  31. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3/core/__init__.py +0 -0
  32. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3/orm/__init__.py +0 -0
  33. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3/orm/fields/base.py +0 -0
  34. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3/orm/fields/misc.py +0 -0
  35. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3/orm/fields/text.py +0 -0
  36. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3.egg-info/dependency_links.txt +0 -0
  37. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3.egg-info/requires.txt +0 -0
  38. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/postgresdb3.egg-info/top_level.txt +0 -0
  39. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/pyproject.toml +0 -0
  40. {postgresdb3-0.7.0 → postgresdb3-1.0.1}/setup.cfg +0 -0
@@ -0,0 +1,302 @@
1
+ Metadata-Version: 2.4
2
+ Name: postgresdb3
3
+ Version: 1.0.1
4
+ Summary: High-Performance Sync and Async PostgreSQL ORM for Python
5
+ Author: Abdulbosit Alijonov
6
+ Project-URL: Source Code, https://github.com/AlijonovUz/PostgresDB
7
+ Classifier: Programming Language :: Python :: 3.9
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: psycopg2>=2.9
13
+ Requires-Dist: asyncpg>=0.31.0
14
+ Dynamic: author
15
+ Dynamic: classifier
16
+ Dynamic: description
17
+ Dynamic: description-content-type
18
+ Dynamic: project-url
19
+ Dynamic: requires-dist
20
+ Dynamic: requires-python
21
+ Dynamic: summary
22
+
23
+ # PostgresDB3 - High-Performance Python ORM
24
+
25
+ **PostgresDB3** — bu PostgreSQL uchun mo'ljallangan zamonaviy, tezkor va ham **sinxron**, ham **asinxron** ishlash imkoniyatiga ega bo'lgan ORM (Object-Relational Mapping) kutubxonasi.
26
+
27
+ U Django ORM kabi qulay va oson tushuniladi, lekin o'zida asinxronlik (`asyncpg`) va ko'plab yuqori texnologik xususiyatlarni mujassamlashtirgan. Kichik botlardan tortib, o'ta katta masshtabdagi (Highload) loyihalargacha bemalol ishlata olasiz!
28
+
29
+ ---
30
+
31
+ ## 📦 O'rnatish
32
+
33
+ Kutubxonani o'rnatish uchun terminalda quyidagi buyruqni kiriting:
34
+
35
+ ```bash
36
+ pip install postgresdb3
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 🚀 Tezkor Boshlash
42
+
43
+ PostgresDB3 bir vaqtning o'zida ikkita dunyoni qo'llab-quvvatlaydi. Xohlasangiz **Sinxron**, xohlasangiz **Asinxron** loyihalarda bir xil sintaksis bilan ishlay olasiz.
44
+
45
+ ### 1. Ulanishni sozlash
46
+
47
+ ```python
48
+ from postgresdb3 import PostgresDB, AsyncPostgresDB
49
+
50
+ # Sinxron ulanish (psycopg2 asosida)
51
+ db_sync = PostgresDB("my_db", "user", "password", host="localhost", port=5432, echo=True)
52
+
53
+ # Asinxron ulanish (asyncpg asosida)
54
+ db_async = AsyncPostgresDB("my_db", "user", "password", host="localhost", port=5432, echo=True)
55
+ ```
56
+ *(Eslatma: `echo=True` yoqilsa, barcha bajarilayotgan SQL so'rovlar terminalda ko'rinib turadi, bu debug uchun juda foydali).*
57
+
58
+ ### 2. Modellarni Yaratish
59
+
60
+ ```python
61
+ from postgresdb3.orm.models import Model, AsyncModel
62
+ from postgresdb3 import String, Integer, Float
63
+
64
+ # Sinxron model
65
+ Model.db = db_sync
66
+
67
+ class User(Model):
68
+ name = String(length=50)
69
+ age = Integer(default=18)
70
+ score = Float(default=0.0)
71
+
72
+ # Asinxron model
73
+ AsyncModel.db = db_async
74
+
75
+ class AsyncUser(AsyncModel):
76
+ name = String(length=50)
77
+ age = Integer(default=18)
78
+ score = Float(default=0.0)
79
+
80
+ # Qo'shimcha sozlamalar (Murakkab Indekslar)
81
+ class Meta:
82
+ unique_together = (("name", "age"),) # Ism va yosh bir xil takrorlanmasligi kerak
83
+ index_together = (("score",),) # Qidiruvni tezlashtirish uchun index
84
+ ```
85
+
86
+ ### 3. CRUD (Yaratish, O'qish, Yangilash, O'chirish)
87
+
88
+ **Sinxron:**
89
+ ```python
90
+ # Yaratish
91
+ user = User.create(name="Ali", age=25)
92
+
93
+ # Barchasini olish
94
+ users = User.all()
95
+
96
+ # Qidirish
97
+ user = User.query().filter(name="Ali").first()
98
+
99
+ # Yangilash
100
+ user.score = 99.5
101
+ user.save()
102
+
103
+ # O'chirish
104
+ user.delete()
105
+ ```
106
+
107
+ **Asinxron:**
108
+ ```python
109
+ # Yaratish
110
+ user = await AsyncUser.create(name="Vali", age=22)
111
+
112
+ # Barchasini olish
113
+ users = await AsyncUser.all()
114
+
115
+ # Qidirish
116
+ user = await AsyncUser.query().filter(name="Vali").first()
117
+
118
+ # Yangilash
119
+ user.score = 100.0
120
+ await user.save()
121
+
122
+ # O'chirish
123
+ await user.delete()
124
+ ```
125
+
126
+ ### 4. Raw SQL dan Model Olish
127
+ Ba'zida juda murakkab yoki spesifik SQL yozishga to'g'ri keladi. Shunday paytda u oddiy `dict` emas, to'g'ridan to'g'ri Model obyekti bo'lib qaytishi kerak:
128
+
129
+ ```python
130
+ # Sinxron
131
+ users = User.raw_sql("SELECT * FROM users WHERE age > %s", 20)
132
+ print(users[0].name) # Bu Model Obyekti!
133
+
134
+ # Asinxron
135
+ users = await AsyncUser.raw_sql("SELECT * FROM asyncusers WHERE age > $1", 20)
136
+ ```
137
+
138
+ ---
139
+
140
+ ## 🔄 Migratsiya (Django uslubida)
141
+
142
+ Siz o'z loyihangiz papkasida bitta `manage.py` yaratib olib, jadvallarni SQL o'qib-o'tirmasdan terminal orqali avtomatik yangilab borishingiz mumkin.
143
+
144
+ **`manage.py` yaratamiz:**
145
+ ```python
146
+ import sys
147
+ from postgresdb3 import execute_from_command_line
148
+ from myapp.models import db_sync # 1. Sizning bazaga ulangan db obyektingiz
149
+
150
+ # 2. DIQQAT: Migratsiya dvigateli modellarni ko'rishi uchun
151
+ # ularni albatta import qilib qo'yishingiz SHART!
152
+ from myapp.models import User, Post, Tag
153
+
154
+ if __name__ == "__main__":
155
+ execute_from_command_line(db_sync, sys.argv)
156
+ ```
157
+
158
+ **Terminalda:**
159
+ ```bash
160
+ # 1. Modellar asosida migratsiya faylini tayyorlash
161
+ python manage.py makemigrations initial_setup
162
+
163
+ # 2. Bazaga jadvallarni qo'shish
164
+ python manage.py migrate
165
+
166
+ # 3. Oxirgi migratsiyani bekor qilish va qaytarish (Rollback)
167
+ python manage.py undo
168
+ ```
169
+ *Tizim jadval qo'shish, ustunlarni o'zgartirish va `Meta` klassidagi indekslarni avtomatik o'zi hal qiladi! Xato qilsangiz, `undo` orqali bir soniyada hammasini orqaga qaytara olasiz.*
170
+
171
+ ---
172
+
173
+ ## 🔍 Murakkab Qidiruv va Filtrlar (Q va F)
174
+
175
+ **Q Obyekti (Murakkab shartlar - AND, OR):**
176
+ ```python
177
+ from postgresdb3 import Q
178
+
179
+ # OR (|) sharti
180
+ users = User.query().filter(Q(age__gt=20) | Q(name="Ali")).all()
181
+
182
+ # AND (&) sharti
183
+ users = User.query().filter(Q(age__lt=30) & Q(score__gt=50)).all()
184
+ ```
185
+
186
+ **F Obyekti (Ustunlarni bir-biriga solishtirish yoki yangilash):**
187
+ ```python
188
+ from postgresdb3 import F
189
+
190
+ # Yoshiga nisbatan score'i katta bo'lganlarni izlash
191
+ users = User.query().filter(score__gt=F("age")).all()
192
+
193
+ # Barchaning balini bazaning o'zida +10 ga oshirish
194
+ User.query().update(score=F("score") + 10)
195
+ ```
196
+
197
+ ---
198
+
199
+ ## 🔗 Aloqalar (Relations) va N+1 Yechimi
200
+
201
+ Loyiha `ForeignKey`, `OneToOneField` va `ManyToManyField` kabi turlarni to'liq qo'llab-quvvatlaydi.
202
+
203
+ ```python
204
+ from postgresdb3 import ForeignKey, ManyToManyField
205
+
206
+ class Post(Model):
207
+ title = String(length=100)
208
+ author = ForeignKey(User, related_name="posts")
209
+
210
+ class Tag(Model):
211
+ name = String(length=50)
212
+ posts = ManyToManyField(Post, related_name="tags")
213
+ ```
214
+
215
+ **N+1 xatoligini chetlab o'tish:**
216
+ Odatda chet el kalitlari bilan ishlaganda ko'plab ortiqcha so'rovlar yuzaga keladi. Bunga qarshi quyidagilardan foydalaning:
217
+
218
+ ```python
219
+ # ForeignKey uchun
220
+ posts = Post.query().select_related("author").all()
221
+ print(posts[0].author.name) # 1 ta SQL query bilan ish bitadi
222
+
223
+ # ManyToMany uchun
224
+ posts = Post.query().prefetch_related("tags").all()
225
+ for p in posts:
226
+ print(p.tags) # N+1 muammosi bo'lmaydi
227
+ ```
228
+
229
+ ---
230
+
231
+ ## 📊 Katta Ma'lumotlar bilan Ishlash (Bulk & Pagination)
232
+
233
+ **Ommaviy Yozish (Bulk Create):**
234
+ 10,000 ta obyekti birma-bir emas, bitta so'rov orqali kiritish:
235
+ ```python
236
+ users = [User(name=f"U-{i}", age=20) for i in range(10000)]
237
+ User.bulk_create(users)
238
+ ```
239
+
240
+ **Ommaviy Yangilash (Bulk Update):**
241
+ ```python
242
+ users = User.all()
243
+ for u in users:
244
+ u.age += 1
245
+ User.bulk_update(users, fields=["age"])
246
+ ```
247
+
248
+ **Sahifalash (Pagination):**
249
+ Foydalanuvchiga ma'lumotlarni qismlab (limit/offset bilan avtomatik) taqdim etish:
250
+ ```python
251
+ result = User.query().paginate(page=1, per_page=20)
252
+ print(result["total"]) # Jami elementlar soni
253
+ print(result["pages"]) # Jami sahifalar soni
254
+ print(result["has_next"]) # Keyingi sahifa bormi? (True/False)
255
+ print(result["data"]) # Modellar ro'yxati (20 ta)
256
+ ```
257
+
258
+ ---
259
+
260
+ ## 🛡 Tranzaksiyalar (Xavfsizlik)
261
+
262
+ Muhim operatsiyalar (masalan, pul o'tkazish) vaqtida xato yuz bersa, barcha qilingan ishlarni avtomatik bekor qilish (Rollback):
263
+
264
+ **Sinxron:**
265
+ ```python
266
+ with db_sync.transaction():
267
+ user1.score -= 50
268
+ user1.save()
269
+ user2.score += 50
270
+ user2.save()
271
+ # Agar shu joyda qandaydir xatolik chiqsa, hech qaysi userning puli yechilmaydi!
272
+ ```
273
+
274
+ **Asinxron:**
275
+ ```python
276
+ async with db_async.transaction():
277
+ user1.score -= 50
278
+ await user1.save()
279
+ user2.score += 50
280
+ await user2.save()
281
+ ```
282
+
283
+ ---
284
+
285
+ ## 📈 Agregatsiya (Sum, Avg, Min, Max, Count)
286
+
287
+ Baza orqali kalkulyatsiyalarni amalga oshirish:
288
+
289
+ ```python
290
+ from postgresdb3 import Sum, Avg, Max
291
+
292
+ result = User.query().aggregate(
293
+ total_score=Sum("score"),
294
+ avg_age=Avg("age"),
295
+ max_score=Max("score")
296
+ )
297
+ print(result) # {'total_score': 1500, 'avg_age': 25, 'max_score': 100}
298
+ ```
299
+
300
+ ---
301
+
302
+ *Ushbu ORM kutubxonasi tezlik va xavfsizlikni birinchi o'ringa qoyuvchi mutaxassislar uchun maxsus qurilgan. Mazza qilib foydalaning!*
@@ -0,0 +1,280 @@
1
+ # PostgresDB3 - High-Performance Python ORM
2
+
3
+ **PostgresDB3** — bu PostgreSQL uchun mo'ljallangan zamonaviy, tezkor va ham **sinxron**, ham **asinxron** ishlash imkoniyatiga ega bo'lgan ORM (Object-Relational Mapping) kutubxonasi.
4
+
5
+ U Django ORM kabi qulay va oson tushuniladi, lekin o'zida asinxronlik (`asyncpg`) va ko'plab yuqori texnologik xususiyatlarni mujassamlashtirgan. Kichik botlardan tortib, o'ta katta masshtabdagi (Highload) loyihalargacha bemalol ishlata olasiz!
6
+
7
+ ---
8
+
9
+ ## 📦 O'rnatish
10
+
11
+ Kutubxonani o'rnatish uchun terminalda quyidagi buyruqni kiriting:
12
+
13
+ ```bash
14
+ pip install postgresdb3
15
+ ```
16
+
17
+ ---
18
+
19
+ ## 🚀 Tezkor Boshlash
20
+
21
+ PostgresDB3 bir vaqtning o'zida ikkita dunyoni qo'llab-quvvatlaydi. Xohlasangiz **Sinxron**, xohlasangiz **Asinxron** loyihalarda bir xil sintaksis bilan ishlay olasiz.
22
+
23
+ ### 1. Ulanishni sozlash
24
+
25
+ ```python
26
+ from postgresdb3 import PostgresDB, AsyncPostgresDB
27
+
28
+ # Sinxron ulanish (psycopg2 asosida)
29
+ db_sync = PostgresDB("my_db", "user", "password", host="localhost", port=5432, echo=True)
30
+
31
+ # Asinxron ulanish (asyncpg asosida)
32
+ db_async = AsyncPostgresDB("my_db", "user", "password", host="localhost", port=5432, echo=True)
33
+ ```
34
+ *(Eslatma: `echo=True` yoqilsa, barcha bajarilayotgan SQL so'rovlar terminalda ko'rinib turadi, bu debug uchun juda foydali).*
35
+
36
+ ### 2. Modellarni Yaratish
37
+
38
+ ```python
39
+ from postgresdb3.orm.models import Model, AsyncModel
40
+ from postgresdb3 import String, Integer, Float
41
+
42
+ # Sinxron model
43
+ Model.db = db_sync
44
+
45
+ class User(Model):
46
+ name = String(length=50)
47
+ age = Integer(default=18)
48
+ score = Float(default=0.0)
49
+
50
+ # Asinxron model
51
+ AsyncModel.db = db_async
52
+
53
+ class AsyncUser(AsyncModel):
54
+ name = String(length=50)
55
+ age = Integer(default=18)
56
+ score = Float(default=0.0)
57
+
58
+ # Qo'shimcha sozlamalar (Murakkab Indekslar)
59
+ class Meta:
60
+ unique_together = (("name", "age"),) # Ism va yosh bir xil takrorlanmasligi kerak
61
+ index_together = (("score",),) # Qidiruvni tezlashtirish uchun index
62
+ ```
63
+
64
+ ### 3. CRUD (Yaratish, O'qish, Yangilash, O'chirish)
65
+
66
+ **Sinxron:**
67
+ ```python
68
+ # Yaratish
69
+ user = User.create(name="Ali", age=25)
70
+
71
+ # Barchasini olish
72
+ users = User.all()
73
+
74
+ # Qidirish
75
+ user = User.query().filter(name="Ali").first()
76
+
77
+ # Yangilash
78
+ user.score = 99.5
79
+ user.save()
80
+
81
+ # O'chirish
82
+ user.delete()
83
+ ```
84
+
85
+ **Asinxron:**
86
+ ```python
87
+ # Yaratish
88
+ user = await AsyncUser.create(name="Vali", age=22)
89
+
90
+ # Barchasini olish
91
+ users = await AsyncUser.all()
92
+
93
+ # Qidirish
94
+ user = await AsyncUser.query().filter(name="Vali").first()
95
+
96
+ # Yangilash
97
+ user.score = 100.0
98
+ await user.save()
99
+
100
+ # O'chirish
101
+ await user.delete()
102
+ ```
103
+
104
+ ### 4. Raw SQL dan Model Olish
105
+ Ba'zida juda murakkab yoki spesifik SQL yozishga to'g'ri keladi. Shunday paytda u oddiy `dict` emas, to'g'ridan to'g'ri Model obyekti bo'lib qaytishi kerak:
106
+
107
+ ```python
108
+ # Sinxron
109
+ users = User.raw_sql("SELECT * FROM users WHERE age > %s", 20)
110
+ print(users[0].name) # Bu Model Obyekti!
111
+
112
+ # Asinxron
113
+ users = await AsyncUser.raw_sql("SELECT * FROM asyncusers WHERE age > $1", 20)
114
+ ```
115
+
116
+ ---
117
+
118
+ ## 🔄 Migratsiya (Django uslubida)
119
+
120
+ Siz o'z loyihangiz papkasida bitta `manage.py` yaratib olib, jadvallarni SQL o'qib-o'tirmasdan terminal orqali avtomatik yangilab borishingiz mumkin.
121
+
122
+ **`manage.py` yaratamiz:**
123
+ ```python
124
+ import sys
125
+ from postgresdb3 import execute_from_command_line
126
+ from myapp.models import db_sync # 1. Sizning bazaga ulangan db obyektingiz
127
+
128
+ # 2. DIQQAT: Migratsiya dvigateli modellarni ko'rishi uchun
129
+ # ularni albatta import qilib qo'yishingiz SHART!
130
+ from myapp.models import User, Post, Tag
131
+
132
+ if __name__ == "__main__":
133
+ execute_from_command_line(db_sync, sys.argv)
134
+ ```
135
+
136
+ **Terminalda:**
137
+ ```bash
138
+ # 1. Modellar asosida migratsiya faylini tayyorlash
139
+ python manage.py makemigrations initial_setup
140
+
141
+ # 2. Bazaga jadvallarni qo'shish
142
+ python manage.py migrate
143
+
144
+ # 3. Oxirgi migratsiyani bekor qilish va qaytarish (Rollback)
145
+ python manage.py undo
146
+ ```
147
+ *Tizim jadval qo'shish, ustunlarni o'zgartirish va `Meta` klassidagi indekslarni avtomatik o'zi hal qiladi! Xato qilsangiz, `undo` orqali bir soniyada hammasini orqaga qaytara olasiz.*
148
+
149
+ ---
150
+
151
+ ## 🔍 Murakkab Qidiruv va Filtrlar (Q va F)
152
+
153
+ **Q Obyekti (Murakkab shartlar - AND, OR):**
154
+ ```python
155
+ from postgresdb3 import Q
156
+
157
+ # OR (|) sharti
158
+ users = User.query().filter(Q(age__gt=20) | Q(name="Ali")).all()
159
+
160
+ # AND (&) sharti
161
+ users = User.query().filter(Q(age__lt=30) & Q(score__gt=50)).all()
162
+ ```
163
+
164
+ **F Obyekti (Ustunlarni bir-biriga solishtirish yoki yangilash):**
165
+ ```python
166
+ from postgresdb3 import F
167
+
168
+ # Yoshiga nisbatan score'i katta bo'lganlarni izlash
169
+ users = User.query().filter(score__gt=F("age")).all()
170
+
171
+ # Barchaning balini bazaning o'zida +10 ga oshirish
172
+ User.query().update(score=F("score") + 10)
173
+ ```
174
+
175
+ ---
176
+
177
+ ## 🔗 Aloqalar (Relations) va N+1 Yechimi
178
+
179
+ Loyiha `ForeignKey`, `OneToOneField` va `ManyToManyField` kabi turlarni to'liq qo'llab-quvvatlaydi.
180
+
181
+ ```python
182
+ from postgresdb3 import ForeignKey, ManyToManyField
183
+
184
+ class Post(Model):
185
+ title = String(length=100)
186
+ author = ForeignKey(User, related_name="posts")
187
+
188
+ class Tag(Model):
189
+ name = String(length=50)
190
+ posts = ManyToManyField(Post, related_name="tags")
191
+ ```
192
+
193
+ **N+1 xatoligini chetlab o'tish:**
194
+ Odatda chet el kalitlari bilan ishlaganda ko'plab ortiqcha so'rovlar yuzaga keladi. Bunga qarshi quyidagilardan foydalaning:
195
+
196
+ ```python
197
+ # ForeignKey uchun
198
+ posts = Post.query().select_related("author").all()
199
+ print(posts[0].author.name) # 1 ta SQL query bilan ish bitadi
200
+
201
+ # ManyToMany uchun
202
+ posts = Post.query().prefetch_related("tags").all()
203
+ for p in posts:
204
+ print(p.tags) # N+1 muammosi bo'lmaydi
205
+ ```
206
+
207
+ ---
208
+
209
+ ## 📊 Katta Ma'lumotlar bilan Ishlash (Bulk & Pagination)
210
+
211
+ **Ommaviy Yozish (Bulk Create):**
212
+ 10,000 ta obyekti birma-bir emas, bitta so'rov orqali kiritish:
213
+ ```python
214
+ users = [User(name=f"U-{i}", age=20) for i in range(10000)]
215
+ User.bulk_create(users)
216
+ ```
217
+
218
+ **Ommaviy Yangilash (Bulk Update):**
219
+ ```python
220
+ users = User.all()
221
+ for u in users:
222
+ u.age += 1
223
+ User.bulk_update(users, fields=["age"])
224
+ ```
225
+
226
+ **Sahifalash (Pagination):**
227
+ Foydalanuvchiga ma'lumotlarni qismlab (limit/offset bilan avtomatik) taqdim etish:
228
+ ```python
229
+ result = User.query().paginate(page=1, per_page=20)
230
+ print(result["total"]) # Jami elementlar soni
231
+ print(result["pages"]) # Jami sahifalar soni
232
+ print(result["has_next"]) # Keyingi sahifa bormi? (True/False)
233
+ print(result["data"]) # Modellar ro'yxati (20 ta)
234
+ ```
235
+
236
+ ---
237
+
238
+ ## 🛡 Tranzaksiyalar (Xavfsizlik)
239
+
240
+ Muhim operatsiyalar (masalan, pul o'tkazish) vaqtida xato yuz bersa, barcha qilingan ishlarni avtomatik bekor qilish (Rollback):
241
+
242
+ **Sinxron:**
243
+ ```python
244
+ with db_sync.transaction():
245
+ user1.score -= 50
246
+ user1.save()
247
+ user2.score += 50
248
+ user2.save()
249
+ # Agar shu joyda qandaydir xatolik chiqsa, hech qaysi userning puli yechilmaydi!
250
+ ```
251
+
252
+ **Asinxron:**
253
+ ```python
254
+ async with db_async.transaction():
255
+ user1.score -= 50
256
+ await user1.save()
257
+ user2.score += 50
258
+ await user2.save()
259
+ ```
260
+
261
+ ---
262
+
263
+ ## 📈 Agregatsiya (Sum, Avg, Min, Max, Count)
264
+
265
+ Baza orqali kalkulyatsiyalarni amalga oshirish:
266
+
267
+ ```python
268
+ from postgresdb3 import Sum, Avg, Max
269
+
270
+ result = User.query().aggregate(
271
+ total_score=Sum("score"),
272
+ avg_age=Avg("age"),
273
+ max_score=Max("score")
274
+ )
275
+ print(result) # {'total_score': 1500, 'avg_age': 25, 'max_score': 100}
276
+ ```
277
+
278
+ ---
279
+
280
+ *Ushbu ORM kutubxonasi tezlik va xavfsizlikni birinchi o'ringa qoyuvchi mutaxassislar uchun maxsus qurilgan. Mazza qilib foydalaning!*
@@ -0,0 +1,11 @@
1
+ from .core import PostgresDB, AsyncPostgresDB
2
+ from .migrations.engine import MigrationEngine
3
+ from .orm.expressions import Q, F, Sum, Avg, Min, Max, Count
4
+ from .orm.fields import (
5
+ String, Integer, Boolean, Float, Double, Decimal,
6
+ Date, Time, Timestamp, Timestamptz,
7
+ JSON, JSONB, UUID, Array,
8
+ ForeignKey, OneToOneField, ManyToManyField,
9
+ Serial, BigSerial, SmallInteger, BigInteger, Text
10
+ )
11
+ from .cli import execute_from_command_line
@@ -0,0 +1,62 @@
1
+ import sys
2
+ import argparse
3
+ import asyncio
4
+ from .migrations.engine import MigrationEngine
5
+ from .core import PostgresDB, AsyncPostgresDB
6
+
7
+
8
+ def execute_from_command_line(db, argv=None):
9
+ """
10
+ Kutubxonadan foydalanuvchilar o'z loyihalarida terminal buyruqlarini
11
+ ishga tushirishi uchun maxsus CLI funksiyasi (xuddi Django manage.py kabi).
12
+ """
13
+ if argv is None:
14
+ argv = sys.argv
15
+
16
+ parser = argparse.ArgumentParser(description="PostgresDB CLI - Ma'lumotlar bazasini boshqarish")
17
+ subparsers = parser.add_subparsers(dest="command", help="Mavjud buyruqlar")
18
+
19
+
20
+ make_parser = subparsers.add_parser("makemigrations", help="Modellardagi o'zgarishlar asosida yangi migratsiya fayllarini yaratadi")
21
+ make_parser.add_argument("name", nargs="?", default="auto", help="Migratsiya nomi (masalan: initial_setup)")
22
+
23
+
24
+ subparsers.add_parser("migrate", help="Mavjud migratsiyalarni ma'lumotlar bazasiga qo'llaydi")
25
+ subparsers.add_parser("undo", help="Oxirgi migratsiyani bekor qiladi va bazadan o'chiradi")
26
+
27
+ args = parser.parse_args(argv[1:])
28
+
29
+ if args.command == "makemigrations":
30
+ engine = MigrationEngine()
31
+ print(f"'{args.name}' nomli migratsiya yaratilmoqda...")
32
+ engine.makemigrations(args.name)
33
+
34
+ elif args.command == "migrate":
35
+ engine = MigrationEngine()
36
+ if isinstance(db, PostgresDB):
37
+ engine.migrate(db)
38
+ elif isinstance(db, AsyncPostgresDB):
39
+
40
+ loop = asyncio.get_event_loop()
41
+ if loop.is_running():
42
+ asyncio.ensure_future(engine.async_migrate(db))
43
+ else:
44
+ loop.run_until_complete(engine.async_migrate(db))
45
+ else:
46
+ print("Xato: Noma'lum DB obyekti (PostgresDB yoki AsyncPostgresDB kerak).")
47
+
48
+ elif args.command == "undo":
49
+ engine = MigrationEngine()
50
+ if isinstance(db, PostgresDB):
51
+ engine.undo_migration(db)
52
+ elif isinstance(db, AsyncPostgresDB):
53
+ loop = asyncio.get_event_loop()
54
+ if loop.is_running():
55
+ asyncio.ensure_future(engine.async_undo_migration(db))
56
+ else:
57
+ loop.run_until_complete(engine.async_undo_migration(db))
58
+ else:
59
+ print("Xato: Noma'lum DB obyekti (PostgresDB yoki AsyncPostgresDB kerak).")
60
+
61
+ else:
62
+ parser.print_help()