aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2026-09-25 09:39:14 +0200
committerDaniel Schadt <kingdread@gmx.de>2026-09-25 09:39:14 +0200
commit3a5187c118aba5eac93e85c9394346fc49fed604 (patch)
tree98ba3b5c130a98b1dd7618b7ffe87f45141415ce
parentff56efd935d3c68fb9db1921819bef43020b9212 (diff)
downloadfietsboek-3a5187c118aba5eac93e85c9394346fc49fed604.tar.gz
fietsboek-3a5187c118aba5eac93e85c9394346fc49fed604.tar.bz2
fietsboek-3a5187c118aba5eac93e85c9394346fc49fed604.zip
add climb modelclimbs
-rw-r--r--fietsboek/models/__init__.py1
-rw-r--r--fietsboek/models/climb.py64
-rw-r--r--fietsboek/models/track.py8
3 files changed, 73 insertions, 0 deletions
diff --git a/fietsboek/models/__init__.py b/fietsboek/models/__init__.py
index 004ed8e..4d4fcaf 100644
--- a/fietsboek/models/__init__.py
+++ b/fietsboek/models/__init__.py
@@ -9,6 +9,7 @@ from sqlalchemy import engine_from_config, event
from sqlalchemy.orm import configure_mappers, sessionmaker
from .badge import Badge # flake8: noqa
+from .climb import Climb # flake8: noqa
from .comment import Comment # flake8: noqa
from .image import ImageMetadata # flake8: noqa
from .journey import Journey
diff --git a/fietsboek/models/climb.py b/fietsboek/models/climb.py
new file mode 100644
index 0000000..3dd8d17
--- /dev/null
+++ b/fietsboek/models/climb.py
@@ -0,0 +1,64 @@
+"""The Climb model."""
+
+from typing import TYPE_CHECKING
+
+from pyramid.httpexceptions import HTTPNotFound
+from pyramid.request import Request
+from sqlalchemy import ForeignKey, Integer, LargeBinary, Text, select
+from sqlalchemy.orm import Mapped, mapped_column, relationship
+
+from .meta import Base
+from ..geo import Path
+
+if TYPE_CHECKING:
+ from .track import Track
+
+
+class Climb(Base):
+
+ # pylint: disable=too-few-public-methods
+ __tablename__ = "climbs"
+ id: Mapped[int] = mapped_column(Integer, primary_key=True)
+ track_id: Mapped[int] = mapped_column(Integer, ForeignKey("tracks.id"), nullable=False)
+ automatic_name: Mapped[str | None] = mapped_column(Text)
+ given_name: Mapped[str | None] = mapped_column(Text)
+ image: Mapped[bytes] = mapped_column(LargeBinary)
+
+ start_index: Mapped[int] = mapped_column(Integer, nullable=False)
+ end_index: Mapped[int] = mapped_column(Integer, nullable=False)
+
+ track: Mapped[Track] = relationship("Track", back_populates="climbs")
+
+ @classmethod
+ def factory(cls, request: Request) -> "Climb":
+ """Factory method to pass to a route definition.
+
+ This factory retrieves the climb based on the ``climb_id`` matched
+ route parameter, and returns the climb. If the climb is not found,
+ ``HTTPNotFound`` is raised.
+
+ :raises pyramid.httpexception.NotFound: If the climb is not found.
+ :param request: The pyramid request.
+ :return: The climb.
+ """
+ query = select(cls).filter_by(id=request.matchdict["climb_id"])
+ climb_object = request.dbsession.execute(query).scalar_one_or_none()
+ if climb_object is None:
+ raise HTTPNotFound()
+ return climb_object
+
+ def __acl__(self):
+ # Delegate all access handling to the track this climb belongs to
+ return self.track.__acl__()
+
+ def path(self) -> Path:
+ """Returns the path of this climb."""
+ path = self.track.path()
+ return Path(path.points[self.start_index:self.end_index])
+
+ def display_name(self) -> str:
+ if self.given_name:
+ return self.given_name
+ return self.automatic_name
+
+__all__ = ["Climb"]
diff --git a/fietsboek/models/track.py b/fietsboek/models/track.py
index 95e341f..361cc12 100644
--- a/fietsboek/models/track.py
+++ b/fietsboek/models/track.py
@@ -309,6 +309,9 @@ class Track(Base):
cache: Mapped[Optional["TrackCache"]] = relationship(
"TrackCache", back_populates="track", uselist=False, cascade="all, delete-orphan"
)
+ climbs: Mapped[list["models.Climb"]] = relationship(
+ "Climb", back_populates="track", cascade="all, delete-orphan"
+ )
tagged_people: Mapped[list["models.User"]] = relationship(
"User", secondary=track_people_assoc, back_populates="tagged_tracks"
)
@@ -854,6 +857,11 @@ class TrackWithMetadata:
return self.track.badges[:]
@property
+ def climbs(self) -> list["models.Climb"]:
+ """Climbs of the underlying track."""
+ return self.track.climbs[:]
+
+ @property
def tags(self) -> list["models.Tag"]:
"""Tags of the underlying track."""
return self.track.tags[:]