- Fase A: license templates, search history, cost estimator - Fase B: import URL, bulk ZIP, batch download - Fase C: comparison mode, mesh validation, measurement tool - Fase D: cross-section clipping, overhang heatmap, layer animation - Refactor Pydantic/SQLAlchemy warnings - 24 tests pytest - README actualizado - WebP thumbnails, lazy loading, cache headers
106 lines
3.8 KiB
Python
106 lines
3.8 KiB
Python
from sqlalchemy import Column, Integer, String, Float, DateTime, Text, Boolean, Table, ForeignKey
|
|
from sqlalchemy.orm import relationship
|
|
from datetime import datetime, timezone
|
|
from app.database import Base
|
|
|
|
# Many-to-many association tables
|
|
model_tags = Table(
|
|
'model_tags',
|
|
Base.metadata,
|
|
Column('model_id', Integer, ForeignKey('models.id'), primary_key=True),
|
|
Column('tag_id', Integer, ForeignKey('tags.id'), primary_key=True)
|
|
)
|
|
|
|
collection_models = Table(
|
|
'collection_models',
|
|
Base.metadata,
|
|
Column('collection_id', Integer, ForeignKey('collections.id'), primary_key=True),
|
|
Column('model_id', Integer, ForeignKey('models.id'), primary_key=True)
|
|
)
|
|
|
|
|
|
class Tag(Base):
|
|
__tablename__ = "tags"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
name = Column(String, unique=True, nullable=False, index=True)
|
|
|
|
models = relationship("Model3D", secondary=model_tags, back_populates="tags")
|
|
|
|
|
|
class Model3D(Base):
|
|
__tablename__ = "models"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
title = Column(String, nullable=False)
|
|
filename = Column(String, nullable=False)
|
|
description = Column(Text, nullable=True)
|
|
author = Column(String, nullable=True)
|
|
license = Column(String, nullable=True)
|
|
category = Column(String, nullable=True)
|
|
file_size = Column(Integer, nullable=True)
|
|
file_hash = Column(String, nullable=True, index=True)
|
|
width = Column(Float, nullable=True)
|
|
height = Column(Float, nullable=True)
|
|
depth = Column(Float, nullable=True)
|
|
faces = Column(Integer, nullable=True)
|
|
created_at = Column(DateTime, default=datetime.now(timezone.utc))
|
|
thumbnail_path = Column(String, nullable=True)
|
|
download_count = Column(Integer, default=0)
|
|
|
|
tags = relationship("Tag", secondary=model_tags, back_populates="models")
|
|
files = relationship("ModelFile", back_populates="model", cascade="all, delete-orphan")
|
|
ratings = relationship("Rating", back_populates="model", cascade="all, delete-orphan")
|
|
comments = relationship("Comment", back_populates="model", cascade="all, delete-orphan")
|
|
collections = relationship("Collection", secondary=collection_models, back_populates="models")
|
|
|
|
|
|
class ModelFile(Base):
|
|
__tablename__ = "model_files"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
model_id = Column(Integer, ForeignKey("models.id"), nullable=False)
|
|
filename = Column(String, nullable=False)
|
|
file_path = Column(String, nullable=False)
|
|
file_type = Column(String, nullable=False, default='stl')
|
|
part_name = Column(String, nullable=True)
|
|
is_primary = Column(Boolean, default=False)
|
|
file_size = Column(Integer, nullable=True)
|
|
file_hash = Column(String, nullable=True)
|
|
|
|
model = relationship("Model3D", back_populates="files")
|
|
|
|
|
|
class Rating(Base):
|
|
__tablename__ = "ratings"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
model_id = Column(Integer, ForeignKey("models.id"), nullable=False)
|
|
stars = Column(Integer, nullable=False) # 1-5
|
|
created_at = Column(DateTime, default=datetime.now(timezone.utc))
|
|
|
|
model = relationship("Model3D", back_populates="ratings")
|
|
|
|
|
|
class Collection(Base):
|
|
__tablename__ = "collections"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
name = Column(String, nullable=False)
|
|
description = Column(Text, nullable=True)
|
|
created_at = Column(DateTime, default=datetime.now(timezone.utc))
|
|
|
|
models = relationship("Model3D", secondary=collection_models, back_populates="collections")
|
|
|
|
|
|
class Comment(Base):
|
|
__tablename__ = "comments"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
model_id = Column(Integer, ForeignKey("models.id"), nullable=False)
|
|
author_name = Column(String, nullable=True)
|
|
text = Column(Text, nullable=False)
|
|
created_at = Column(DateTime, default=datetime.now(timezone.utc))
|
|
|
|
model = relationship("Model3D", back_populates="comments")
|