# plugins/media/models.py from datetime import datetime from flask import url_for from app import db class Media(db.Model): __tablename__ = "media" __table_args__ = {"extend_existing": True} id = db.Column(db.Integer, primary_key=True) plugin = db.Column(db.String(50), nullable=False) related_id = db.Column(db.Integer, nullable=False) filename = db.Column(db.String(256), nullable=False) uploaded_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) uploader_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False) caption = db.Column(db.String(255), nullable=True) plant_id = db.Column(db.Integer, db.ForeignKey("plant.id"), nullable=True) growlog_id = db.Column(db.Integer, db.ForeignKey("grow_logs.id"), nullable=True) created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) # You already have a file_url column in your DB file_url = db.Column(db.String(512), nullable=False) hearts = db.relationship( "plugins.media.models.ImageHeart", backref="media", lazy="dynamic", cascade="all, delete-orphan", ) featured_entries = db.relationship( "plugins.media.models.FeaturedImage", backref="media", lazy="dynamic", cascade="all, delete-orphan", ) plant = db.relationship( "plugins.plant.models.Plant", back_populates="media_items", foreign_keys=[plant_id], lazy="joined", ) growlog = db.relationship( "plugins.growlog.models.GrowLog", back_populates="media_items", foreign_keys=[growlog_id], lazy="joined", ) def __init__(self, *args, **kwargs): """ Infer plugin & related_id from whichever FK is set, and build the file_url path immediately so that INSERT never tries to write plugin=None or related_id=None. """ super().__init__(*args, **kwargs) # If they passed plant_id or growlog_id in kwargs, pick one: if self.plant_id: self.plugin = "plants" self.related_id = self.plant_id elif self.growlog_id: self.plugin = "grow_logs" self.related_id = self.growlog_id else: # fallback (you might choose to raise instead) self.plugin = kwargs.get("plugin", "") self.related_id = kwargs.get("related_id", 0) # They must also supply `filename` before commit. # Build `file_url` in the same format your property used to: date_path = self.uploaded_at.strftime("%Y/%m/%d") self.file_url = f"{self.plugin}/{self.related_id}/{date_path}/{self.filename}" @property def url(self): return url_for("media.media_file", filename=self.file_url) @property def featured(self): return any( fe.context == "plant" and fe.is_featured for fe in self.featured_entries ) class ImageHeart(db.Model): __tablename__ = "image_hearts" __table_args__ = {"extend_existing": True} id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False) media_id = db.Column(db.Integer, db.ForeignKey("media.id"), nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False) class FeaturedImage(db.Model): __tablename__ = "featured_images" __table_args__ = {"extend_existing": True} id = db.Column(db.Integer, primary_key=True) media_id = db.Column(db.Integer, db.ForeignKey("media.id"), nullable=False) context = db.Column(db.String(50), nullable=False) context_id = db.Column(db.Integer, nullable=False) override_text = db.Column(db.String(255), nullable=True) is_featured = db.Column(db.Boolean, default=True, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)