feat: Added travel models, travel creation command, travels list command with pagination, set help message, improvements and fixes

This commit is contained in:
ITQ
2024-03-23 02:47:05 +03:00
parent 675e5ab891
commit 1802ce81b0
15 changed files with 623 additions and 15 deletions
+7
View File
@@ -0,0 +1,7 @@
# flake8: noqa
from app.models.base import Base
import app.models.user
import app.models.travel
Base.registry.configure()
+5
View File
@@ -0,0 +1,5 @@
from typing import Any
from sqlalchemy.ext.declarative import declarative_base
Base: Any = declarative_base()
+124
View File
@@ -0,0 +1,124 @@
__all__ = ("Travel", "Location")
import sqlalchemy as sa
from sqlalchemy.orm import relationship, validates
from app import session
from app.models import Base
from app.models.user import User
association_table = sa.Table(
"user_travel_association",
Base.metadata,
sa.Column("user_id", sa.BigInteger, sa.ForeignKey("users.telegram_id")),
sa.Column("travel_id", sa.Integer, sa.ForeignKey("travels.id")),
)
class Travel(Base):
__tablename__ = "travels"
id = sa.Column( # noqa: A003
sa.Integer,
unique=True,
primary_key=True,
nullable=False,
autoincrement=True,
index=True,
)
title = sa.Column(
sa.String(50),
nullable=False,
unique=True,
)
description = sa.Column(
sa.String(100),
nullable=True,
)
author_id = sa.Column(
sa.BigInteger,
sa.ForeignKey(User.telegram_id),
nullable=False,
)
users = relationship(
User,
secondary=association_table,
backref="travels",
)
locations = relationship("Location", backref="travel")
notes = relationship("Note", backref="travel")
@validates("title")
def validate_title(self, key, value):
assert len(value) <= 30, "Title must be 30 characters or fewer."
if session.query(Travel).filter(Travel.title == value).first():
raise AssertionError("This title is already taken.")
return value
@validates("description")
def validate_description(self, key, value):
if value is not None:
assert (
len(value) <= 100
), "Description must be 100 characters or fewer."
return value
class Location(Base):
__tablename__ = "locations"
id = sa.Column( # noqa: A003
sa.Integer,
unique=True,
primary_key=True,
autoincrement=True,
index=True,
)
name = sa.Column(sa.Text, nullable=False)
date_start = sa.Column(sa.Date(), nullable=False)
date_end = sa.Column(sa.Date(), nullable=False)
travel_id = sa.Column(
sa.Integer,
sa.ForeignKey("travels.id"),
nullable=False,
)
class Note(Base):
__tablename__ = "notes"
id = sa.Column( # noqa: A003
sa.Integer,
unique=True,
primary_key=True,
autoincrement=True,
index=True,
)
file_id = sa.Column(sa.Text, nullable=False)
file_name = sa.Column(sa.Text, nullable=False)
file_type = sa.Column(sa.Text, nullable=False)
public: sa.Column[bool] = sa.Column(
sa.Boolean(),
nullable=False,
default=False,
)
author_id = sa.Column(
sa.BigInteger,
sa.ForeignKey(User.telegram_id),
nullable=False,
)
travel_id = sa.Column(
sa.Integer,
sa.ForeignKey("travels.id"),
nullable=False,
)
+8 -6
View File
@@ -1,20 +1,16 @@
__all__ = ("User",)
import re
from typing import Any
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import validates
from sqlalchemy.orm import relationship, validates
from app import session
from app.models import Base
from app.utils import geo
from app.utils.db import utcnow
Base: Any = declarative_base()
class User(Base):
__tablename__ = "users"
@@ -38,6 +34,9 @@ class User(Base):
server_default=utcnow(),
)
notes = relationship("Note", backref="author")
owned_travels = relationship("Travel", backref="author")
@validates("username")
def validate_username(self, key, value):
regex_pattern = re.compile(r"^[a-zA-Z0-9_]{5,20}$")
@@ -98,6 +97,9 @@ class User(Base):
return normalized_value
def get_user_travels(self):
return self.owned_travels + self.travels
def get_human_readable_datejoined(self):
return self.date_joined.strftime("%Y-%m-%d %H:%M:%S")