summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/__init__.py5
-rw-r--r--app/models/collections.py40
-rw-r--r--app/models/image.py9
-rw-r--r--app/models/integrations.py13
-rw-r--r--app/models/profile.py38
-rw-r--r--app/models/user.py33
6 files changed, 82 insertions, 56 deletions
diff --git a/app/models/__init__.py b/app/models/__init__.py
index e69de29..603a57f 100644
--- a/app/models/__init__.py
+++ b/app/models/__init__.py
@@ -0,0 +1,5 @@
+# from .collections import Collection
+from .image import Image
+from .integrations import UserIntegration
+from .profile import Profile
+from .user import User
diff --git a/app/models/collections.py b/app/models/collections.py
index 7dc5bb7..e69de29 100644
--- a/app/models/collections.py
+++ b/app/models/collections.py
@@ -1,40 +0,0 @@
-from __future__ import annotations
-
-from datetime import datetime
-from typing import TYPE_CHECKING
-
-from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, Table
-from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
-
-Base = DeclarativeBase()
-
-if TYPE_CHECKING:
- from .image import Image
-
-collection_images = Table(
- "collection_images",
- Base.metadata,
- mapped_column(
- "collection_id", Integer, ForeignKey("collections.id"), primary_key=True
- ),
- mapped_column("image_id", Integer, ForeignKey("images.id"), primary_key=True),
-)
-
-
-class Collection(Base):
- __tablename__ = "collections"
-
- id: Mapped[int] = mapped_column(Integer, primary_key=True)
- user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), nullable=False)
- name: Mapped[str] = mapped_column(String(100), nullable=False)
- description: Mapped[str | None] = mapped_column(String(500), nullable=True)
- is_private: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
- created_at: Mapped[datetime] = mapped_column(
- DateTime(timezone=True), default=datetime.utcnow
- )
-
- images: Mapped[list["Image"]] = relationship(
- "Image",
- secondary=collection_images,
- back_populates="collections",
- )
diff --git a/app/models/image.py b/app/models/image.py
index e139123..b75b197 100644
--- a/app/models/image.py
+++ b/app/models/image.py
@@ -12,11 +12,12 @@ from sqlalchemy import (
Table,
func,
)
-from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
+from sqlalchemy.orm import Mapped, mapped_column, relationship
-from .collections import Collection
+from app.utils.db import Base
+
+# from .collections import Collection
-Base = DeclarativeBase()
image_tags = Table(
"image_tags",
@@ -63,8 +64,10 @@ class Image(Base):
)
+"""
collections: Mapped[list["Collection"]] = relationship(
"Collection",
secondary="collection_images",
back_populates="images",
)
+"""
diff --git a/app/models/integrations.py b/app/models/integrations.py
index 4a1ddb9..f3eaca4 100644
--- a/app/models/integrations.py
+++ b/app/models/integrations.py
@@ -1,7 +1,12 @@
+from typing import TYPE_CHECKING
+
from sqlalchemy import ForeignKey, Integer, String
-from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
+from sqlalchemy.orm import Mapped, mapped_column, relationship
+
+from app.utils.db import Base
-Base = DeclarativeBase()
+if TYPE_CHECKING:
+ from .user import User
class UserIntegration(Base):
@@ -17,3 +22,7 @@ class UserIntegration(Base):
x: Mapped[str | None] = mapped_column(String(255), nullable=True) # Twitter/X
behance: Mapped[str | None] = mapped_column(String(255), nullable=True)
instagram: Mapped[str | None] = mapped_column(String(255), nullable=True)
+
+ user: Mapped["User"] = relationship(
+ "User", back_populates="integrations", uselist=False
+ )
diff --git a/app/models/profile.py b/app/models/profile.py
index b19d796..93ce6fd 100644
--- a/app/models/profile.py
+++ b/app/models/profile.py
@@ -1,14 +1,28 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from fastapi import Depends
from sqlalchemy import ForeignKey, Integer, String
-from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
+from sqlalchemy.ext.asyncio import AsyncSession
+from sqlalchemy.future import select
+from sqlalchemy.orm import Mapped, mapped_column, relationship
+
+from app.utils.db import Base, get_async_session
-Base = DeclarativeBase()
+if TYPE_CHECKING:
+ from .user import (
+ User,
+ )
class Profile(Base):
__tablename__ = "profiles"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
- user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), unique=True)
+ user_id: Mapped[int] = mapped_column(
+ ForeignKey("users.id"), unique=True, nullable=False
+ )
avatar_file: Mapped[str | None] = mapped_column(String(255), nullable=True)
banner_file: Mapped[str | None] = mapped_column(String(255), nullable=True)
@@ -19,3 +33,21 @@ class Profile(Base):
subscriptions_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
followers_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
following_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
+
+ user: Mapped["User"] = relationship(
+ "User", back_populates="profile", uselist=False, lazy="selectin"
+ )
+
+ @classmethod
+ async def get_by_user_id(
+ cls, user_id: int, session: AsyncSession = Depends(get_async_session)
+ ):
+ result = await session.execute(select(cls).where(cls.user_id == user_id))
+ return result.scalars().first()
+
+ @classmethod
+ async def get_by_id(
+ cls, profile_id: int, session: AsyncSession = Depends(get_async_session)
+ ):
+ result = await session.execute(select(cls).where(cls.id == profile_id))
+ return result.scalars().first()
diff --git a/app/models/user.py b/app/models/user.py
index 8dbe419..442173c 100644
--- a/app/models/user.py
+++ b/app/models/user.py
@@ -1,14 +1,18 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
from fastapi import Depends
from sqlalchemy import Boolean, Integer, String
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
-from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
-
-from app.utils.db import get_async_session
+from sqlalchemy.orm import Mapped, mapped_column, relationship, selectinload
+from app.utils.db import Base, get_async_session
-class Base(DeclarativeBase):
- pass
+if TYPE_CHECKING:
+ from .integrations import UserIntegration
+ from .profile import Profile
class User(Base):
@@ -21,13 +25,19 @@ class User(Base):
google_id: Mapped[str | None] = mapped_column(
String(255), unique=True, nullable=True
)
- avatar_file: Mapped[str | None] = mapped_column(String(255), nullable=True)
- banner_file: Mapped[str | None] = mapped_column(String(255), nullable=True)
+ description: Mapped[str | None] = mapped_column(String(250), nullable=True)
premium: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
is_banned: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
is_moderator: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
token_version: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
+ profile: Mapped["Profile"] = relationship(
+ "Profile", back_populates="user", uselist=False, lazy="selectin"
+ )
+ integrations: Mapped["UserIntegration"] = relationship(
+ "UserIntegration", back_populates="user", uselist=False, lazy="selectin"
+ )
+
@classmethod
async def get_user_by_email(
cls, email: str, session: AsyncSession = Depends(get_async_session)
@@ -39,7 +49,14 @@ class User(Base):
async def get_user_by_username(
cls, username: str, session: AsyncSession = Depends(get_async_session)
):
- result = await session.execute(select(cls).where(cls.username == username))
+ result = await session.execute(
+ select(cls)
+ .options(
+ selectinload(cls.profile),
+ selectinload(cls.integrations),
+ )
+ .where(cls.username == username)
+ )
return result.scalars().first()
@classmethod