Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions docs/databases/development/python/coding/repository.md
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ def test_create_user_error(mock_conn):
)

def test_get_all_users_success(mock_conn):
now = datetime.utcnow()
now = datetime.now()
expected = [{
"id": 1,
"user_name": "john",
Expand Down Expand Up @@ -634,7 +634,7 @@ def test_get_all_users_error(mock_conn):


def test_get_user_by_id_success(mock_conn):
now = datetime.utcnow()
now = datetime.now()
expected = {
"user_name": "john",
"first_name": "John",
Expand Down Expand Up @@ -687,7 +687,7 @@ def test_get_user_by_username_not_found(mock_conn):


def test_update_user_success(mock_conn):
now = datetime.utcnow()
now = datetime.now()
earlier = now - timedelta(hours=1)

dto = {
Expand Down Expand Up @@ -754,7 +754,7 @@ def test_delete_user_not_found(mock_conn):
После этого выполните команду

```bash
pytest-v
pytest -v
```

Если вы все сделали правильно, все тесты пройдены.
Expand Down Expand Up @@ -1212,7 +1212,7 @@ def like_post(post_id: int, user_id: int) -> None:
try:
with pool.connection() as conn:
with conn.cursor() as cur:
cur.execute(query, (post_id, user_id, post_id))
cur.execute(query, (post_id, user_id))
if cur.rowcount == 0:
raise ValueError("Post not found")
except UniqueViolation as err:
Expand All @@ -1237,7 +1237,7 @@ def dislike_post(post_id: int, user_id: int) -> None:

with pool.connection() as conn:
with conn.cursor() as cur:
cur.execute(query, (post_id, user_id, post_id))
cur.execute(query, (post_id, user_id))
if cur.rowcount == 0:
raise ValueError("Post not found")
```
Expand Down Expand Up @@ -1283,7 +1283,7 @@ def test_create_post_success(mock_conn):
expected = {
"id": 1,
"text": dto["text"],
"created_at": datetime.utcnow(),
"created_at": datetime.now(),
"reply_to_id": None,
}

Expand Down Expand Up @@ -1336,7 +1336,7 @@ def test_create_post_success(mock_conn):
expected = {
"id": 1,
"text": dto["text"],
"created_at": datetime.utcnow(),
"created_at": datetime.now(),
"reply_to_id": None,
}

Expand Down Expand Up @@ -1502,7 +1502,7 @@ def test_get_all_posts_error(mock_conn):
def test_get_post_by_id_success(mock_conn):
user_id = 1
post_id = 1
now = datetime.utcnow()
now = datetime.now()

row = {
"post_id": post_id,
Expand Down Expand Up @@ -1668,7 +1668,7 @@ def test_like_post_success(mock_conn):
assert "insert into likes (post_id, user_id)" in normalized_sql

params = mock_cursor.execute.call_args[0][1]
assert params == (post_id, user_id, post_id)
assert params == (post_id, user_id)


def test_like_post_error(mock_conn):
Expand All @@ -1687,7 +1687,7 @@ def test_like_post_error(mock_conn):
assert "insert into likes (post_id, user_id)" in normalized_sql

params = mock_cursor.execute.call_args[0][1]
assert params == (post_id, user_id, post_id)
assert params == (post_id, user_id)


def test_like_post_already_liked(mock_conn):
Expand Down Expand Up @@ -1718,7 +1718,7 @@ def test_dislike_post_success(mock_conn):
assert "delete from likes where post_id = %s and user_id = %s" in normalized_sql

params = mock_cursor.execute.call_args[0][1]
assert params == (post_id, user_id, post_id)
assert params == (post_id, user_id)


def test_dislike_post_error(mock_conn):
Expand All @@ -1737,7 +1737,7 @@ def test_dislike_post_error(mock_conn):
assert "delete from likes where post_id = %s and user_id = %s" in normalized_sql

params = mock_cursor.execute.call_args[0][1]
assert params == (post_id, user_id, post_id)
assert params == (post_id, user_id)


def test_dislike_post_not_found(mock_conn):
Expand All @@ -1756,7 +1756,7 @@ def test_dislike_post_not_found(mock_conn):
assert "delete from likes where post_id = %s and user_id = %s" in normalized_sql

params = mock_cursor.execute.call_args[0][1]
assert params == (post_id, user_id, post_id)
assert params == (post_id, user_id)
```

:::
Expand Down
49 changes: 32 additions & 17 deletions docs/databases/development/python/design/database-connection.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,28 @@

Благодаря этому мы сможем использовать **всю мощь PostgreSQL прямо из кода на Python** — просто, эффективно и без необходимости использовать ORM.

## Установка библиотеки

Прежде чем приступить к изучению возможностей адаптера `psycopg`, необходимо установить соответствующую библиотеку для Python.

Как указано в официальной документации, сначала убедитесь, что версия менеджера пакетов `pip` не ниже 20.3:

```bash
pip install --upgrade pip
```

Затем установите модуль `psycopg[binary]`, который не требует наличия системных зависимостей:

```bash
pip install "psycopg[binary]"
```

Установите `psycopg_pool`:

```bash
pip install psycopg_pool
```

## Основы API библиотеки `psycopg`

Библиотека `psycopg` предоставляет несколько ключевых интерфейсов для работы с PostgreSQL в соответствии со стандартом [**Python DB API 2.0**](https://peps.python.org/pep-0249/).
Expand Down Expand Up @@ -61,30 +83,25 @@ conn.close()
- По умолчанию `psycopg` использует неавтоматические транзакции: нужно вызывать `conn.commit()` или `conn.rollback()`.

Параметры подключения:

```python
psycopg.connect(
host="localhost",
port=5432,
user="postgres",
password="secret",
dbname="mydb",
connect_timeout=10,
application_name="myapp"
)

```
- **host** — адрес сервера PostgreSQL (Например, `localhost` для локального подключения);
- **port** — порт, на котором работает PostgreSQL (По умолчанию - 5432);
- **user** — имя пользователя PostgreSQL;
- **password** — пароль пользователя;
- **dbname** — имя базы данных, к которой осуществляется подключение;
- **connect_timeout** (необязательный параметр) — таймаут в секундах при установке соединения.

Также можно использовать DSN-строку:

```python
psycopg.connect("postgresql://postgres:secret@localhost:5432/mydb")
psycopg.connect(conninfo="postgresql://postgres:secret@localhost:5432/mydb")
```

### 2. Пул подключений (рекомендуемый способ)

Объект `ConnectionPool` из модуля `psycopg_pool` управляет множеством соединений с базой данных. Это более производительный и устойчивый способ подключения в реальных приложениях.

pip install psycopg_pool

#### Пример:

```python
Expand Down Expand Up @@ -277,14 +294,12 @@ pool = ConnectionPool(

```python
import os

from dotenv import load_dotenv
from fastapi import FastAPI, Response, status
from config.db import pool

load_dotenv()

from config.db import pool

app = FastAPI()
port = int(os.getenv("PORT", 3000))

Expand Down