From dac7d95be40f94929b35ab2c434ccbfb6bb30ee1 Mon Sep 17 00:00:00 2001 From: akuzakhemetov Date: Thu, 25 Dec 2025 16:32:17 +0300 Subject: [PATCH] db fix --- database/__init__.py | 5 +- database/models.py | 106 +++++++++++++++++++++++++++++++------------ 2 files changed, 81 insertions(+), 30 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index 100f803..7f6b0d5 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -1,6 +1,6 @@ """Модуль для работы с базой данных""" from database.connection import get_session, async_session_maker, engine -from database.models import User, Book, Author, Genre, Favorite +from database.models import User, Book, Author, Genre, Favorite, UserPreferences __all__ = [ 'get_session', @@ -10,6 +10,7 @@ __all__ = [ 'Book', 'Author', 'Genre', - 'Favorite' + 'Favorite', + 'UserPreferences' ] diff --git a/database/models.py b/database/models.py index fdea460..1086b0e 100644 --- a/database/models.py +++ b/database/models.py @@ -1,6 +1,6 @@ -from sqlalchemy import BigInteger, String, Text, Numeric, Integer, DateTime, Boolean, ForeignKey, Table, Column +from sqlalchemy import BigInteger, String, Text, Numeric, Integer, DateTime, Boolean, ForeignKey, Table, Column, Date from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship -from datetime import datetime +from datetime import datetime, date from typing import Optional, List @@ -12,43 +12,70 @@ class Base(DeclarativeBase): books_book_authors = Table( 'books_book_authors', Base.metadata, - Column('id', Integer, primary_key=True), - Column('book_id', Integer, ForeignKey('books_book.id')), - Column('author_id', Integer, ForeignKey('books_author.id')) + Column('id', BigInteger, primary_key=True), + Column('book_id', BigInteger, ForeignKey('books_book.id')), + Column('author_id', BigInteger, ForeignKey('books_author.id')) ) books_book_genres = Table( 'books_book_genres', Base.metadata, - Column('id', Integer, primary_key=True), - Column('book_id', Integer, ForeignKey('books_book.id')), - Column('genre_id', Integer, ForeignKey('books_genre.id')) + Column('id', BigInteger, primary_key=True), + Column('book_id', BigInteger, ForeignKey('books_book.id')), + Column('genre_id', BigInteger, ForeignKey('books_genre.id')) +) + +# Many-to-Many для любимых жанров пользователя +users_user_favorite_genres = Table( + 'users_user_favorite_genres', + Base.metadata, + Column('id', BigInteger, primary_key=True), + Column('user_id', BigInteger, ForeignKey('users_user.id')), + Column('genre_id', BigInteger, ForeignKey('books_genre.id')) ) class User(Base): - __tablename__ = 'auth_user' + """ + Модель пользователя из Django приложения 'users' + Таблица: users_user + """ + __tablename__ = 'users_user' - id: Mapped[int] = mapped_column(Integer, primary_key=True) - username: Mapped[str] = mapped_column(String(150), unique=True) - email: Mapped[str] = mapped_column(String(254), unique=True) + # Стандартные поля Django AbstractUser + id: Mapped[int] = mapped_column(BigInteger, primary_key=True) password: Mapped[str] = mapped_column(String(128)) - telegram_id: Mapped[Optional[int]] = mapped_column(BigInteger, unique=True, nullable=True) - first_name: Mapped[Optional[str]] = mapped_column(String(150), nullable=True) - last_name: Mapped[Optional[str]] = mapped_column(String(150), nullable=True) - is_active: Mapped[bool] = mapped_column(Boolean, default=True) - is_staff: Mapped[bool] = mapped_column(Boolean, default=False) - is_superuser: Mapped[bool] = mapped_column(Boolean, default=False) - date_joined: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) last_login: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) + is_superuser: Mapped[bool] = mapped_column(Boolean, default=False) + username: Mapped[str] = mapped_column(String(150), unique=True) + first_name: Mapped[str] = mapped_column(String(150), default='') + last_name: Mapped[str] = mapped_column(String(150), default='') + email: Mapped[str] = mapped_column(String(254), unique=True) + is_staff: Mapped[bool] = mapped_column(Boolean, default=False) + is_active: Mapped[bool] = mapped_column(Boolean, default=True) + date_joined: Mapped[datetime] = mapped_column(DateTime) + # Дополнительные поля из модели users.User + phone: Mapped[str] = mapped_column(String(20), default='') + avatar: Mapped[Optional[str]] = mapped_column(String(100), nullable=True) + birth_date: Mapped[Optional[date]] = mapped_column(Date, nullable=True) + about: Mapped[str] = mapped_column(Text, default='') + telegram_id: Mapped[Optional[int]] = mapped_column(BigInteger, unique=True, nullable=True) + is_verified: Mapped[bool] = mapped_column(Boolean, default=False) + last_activity: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) + + # Relationships favorites: Mapped[List["Favorite"]] = relationship(back_populates="user") + favorite_genres: Mapped[List["Genre"]] = relationship( + secondary=users_user_favorite_genres, + back_populates="users" + ) class Author(Base): __tablename__ = 'books_author' - id: Mapped[int] = mapped_column(Integer, primary_key=True) + id: Mapped[int] = mapped_column(BigInteger, primary_key=True) name: Mapped[str] = mapped_column(String(255)) books: Mapped[List["Book"]] = relationship(secondary=books_book_authors, back_populates="authors") @@ -57,24 +84,28 @@ class Author(Base): class Genre(Base): __tablename__ = 'books_genre' - id: Mapped[int] = mapped_column(Integer, primary_key=True) + id: Mapped[int] = mapped_column(BigInteger, primary_key=True) name: Mapped[str] = mapped_column(String(100)) books: Mapped[List["Book"]] = relationship(secondary=books_book_genres, back_populates="genres") + users: Mapped[List[User]] = relationship( + secondary=users_user_favorite_genres, + back_populates="favorite_genres" + ) class Book(Base): __tablename__ = 'books_book' - id: Mapped[int] = mapped_column(Integer, primary_key=True) + id: Mapped[int] = mapped_column(BigInteger, primary_key=True) title: Mapped[str] = mapped_column(String(500)) description: Mapped[Optional[str]] = mapped_column(Text, nullable=True) cover_url: Mapped[Optional[str]] = mapped_column(String(500), nullable=True) average_rating: Mapped[Optional[float]] = mapped_column(Numeric(3, 2), nullable=True) rating_count: Mapped[int] = mapped_column(Integer, default=0) language: Mapped[Optional[str]] = mapped_column(String(10), nullable=True) - created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) - updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) + created_at: Mapped[datetime] = mapped_column(DateTime) + updated_at: Mapped[datetime] = mapped_column(DateTime) deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) authors: Mapped[List[Author]] = relationship(secondary=books_book_authors, back_populates="books") @@ -85,11 +116,30 @@ class Book(Base): class Favorite(Base): __tablename__ = 'books_favorite' - id: Mapped[int] = mapped_column(Integer, primary_key=True) - user_id: Mapped[int] = mapped_column(Integer, ForeignKey('auth_user.id')) - book_id: Mapped[int] = mapped_column(Integer, ForeignKey('books_book.id')) - created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) + id: Mapped[int] = mapped_column(BigInteger, primary_key=True) + user_id: Mapped[int] = mapped_column(BigInteger, ForeignKey('users_user.id')) + book_id: Mapped[int] = mapped_column(BigInteger, ForeignKey('books_book.id')) + created_at: Mapped[datetime] = mapped_column(DateTime) user: Mapped[User] = relationship(back_populates="favorites") book: Mapped[Book] = relationship(back_populates="favorites") + +class UserPreferences(Base): + """ + Настройки пользователя из Django приложения 'users' + Таблица: users_userpreferences + """ + __tablename__ = 'users_userpreferences' + + id: Mapped[int] = mapped_column(BigInteger, primary_key=True) + user_id: Mapped[int] = mapped_column(BigInteger, ForeignKey('users_user.id'), unique=True) + created_at: Mapped[datetime] = mapped_column(DateTime) + updated_at: Mapped[datetime] = mapped_column(DateTime) + language: Mapped[str] = mapped_column(String(10), default='ru') + theme: Mapped[str] = mapped_column(String(20), default='light') + email_notifications: Mapped[bool] = mapped_column(Boolean, default=True) + telegram_notifications: Mapped[bool] = mapped_column(Boolean, default=False) + show_email: Mapped[bool] = mapped_column(Boolean, default=False) + show_phone: Mapped[bool] = mapped_column(Boolean, default=False) +