test ferst

This commit is contained in:
jze9
2026-05-13 19:05:07 +05:00
commit 0ac1c8a862
33 changed files with 3702 additions and 0 deletions

0
api/bd/__init__.py Normal file
View File

44
api/bd/database.py Normal file
View File

@@ -0,0 +1,44 @@
import os
import asyncio
import sqlalchemy
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
from sqlalchemy.orm import DeclarativeBase
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql+asyncpg://postgres:postgres@localhost:5432/news")
REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0")
engine = create_async_engine(DATABASE_URL, pool_size=10, max_overflow=20, echo=False)
AsyncSessionLocal = async_sessionmaker(engine, expire_on_commit=False)
class Base(DeclarativeBase):
pass
async def get_db():
async with AsyncSessionLocal() as session:
yield session
async def wait_for_db():
for attempt in range(30):
try:
async with engine.connect() as conn:
await conn.execute(sqlalchemy.text("SELECT 1"))
return
except Exception:
if attempt == 29:
raise
await asyncio.sleep(2)
import redis.asyncio as aioredis
_redis: aioredis.Redis | None = None
async def get_redis() -> aioredis.Redis:
global _redis
if _redis is None:
_redis = aioredis.from_url(REDIS_URL, encoding="utf-8", decode_responses=True)
return _redis

73
api/bd/models.py Normal file
View File

@@ -0,0 +1,73 @@
import uuid
from datetime import datetime
from sqlalchemy import String, Text, DateTime, ForeignKey, Table, Column, Integer, Enum as SAEnum
from sqlalchemy.orm import mapped_column, Mapped, relationship
from sqlalchemy.dialects.postgresql import UUID
import enum
from .database import Base
class ArticleStatus(str, enum.Enum):
draft = "draft"
published = "published"
article_tag = Table(
"article_tag",
Base.metadata,
Column("article_id", UUID(as_uuid=True), ForeignKey("articles.id", ondelete="CASCADE")),
Column("tag_id", UUID(as_uuid=True), ForeignKey("tags.id", ondelete="CASCADE")),
)
class Category(Base):
__tablename__ = "categories"
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
name: Mapped[str] = mapped_column(String(100), unique=True)
slug: Mapped[str] = mapped_column(String(100), unique=True, index=True)
articles: Mapped[list["Article"]] = relationship(back_populates="category", lazy="noload")
class Tag(Base):
__tablename__ = "tags"
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
name: Mapped[str] = mapped_column(String(100), unique=True)
slug: Mapped[str] = mapped_column(String(100), unique=True, index=True)
class Article(Base):
__tablename__ = "articles"
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
title: Mapped[str] = mapped_column(String(500))
slug: Mapped[str] = mapped_column(String(500), unique=True, index=True)
content: Mapped[str] = mapped_column(Text, default="")
excerpt: Mapped[str] = mapped_column(String(1000), default="")
cover_url: Mapped[str | None] = mapped_column(String(1000), nullable=True)
font_family: Mapped[str] = mapped_column(String(100), default="Merriweather")
status: Mapped[ArticleStatus] = mapped_column(SAEnum(ArticleStatus), default=ArticleStatus.draft)
view_count: Mapped[int] = mapped_column(Integer, default=0)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
published_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
category_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True), ForeignKey("categories.id", ondelete="SET NULL"), nullable=True
)
category: Mapped["Category | None"] = relationship(back_populates="articles", lazy="selectin")
tags: Mapped[list["Tag"]] = relationship(secondary=article_tag, lazy="selectin")
class Admin(Base):
__tablename__ = "admins"
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
username: Mapped[str] = mapped_column(String(100), unique=True)
password_hash: Mapped[str] = mapped_column(String(300))
class Media(Base):
__tablename__ = "media"
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
filename: Mapped[str] = mapped_column(String(500))
url: Mapped[str] = mapped_column(String(1000))
media_type: Mapped[str] = mapped_column(String(20)) # image | video
size_bytes: Mapped[int] = mapped_column(Integer, default=0)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)