feat: implementar 12 mejoras, tests, docs y optimizaciones
- 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
This commit is contained in:
105
app/models.py
Normal file
105
app/models.py
Normal file
@@ -0,0 +1,105 @@
|
||||
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")
|
||||
Reference in New Issue
Block a user