# plugins/plant/models.py from datetime import datetime import uuid as uuid_lib from app import db # Association table for Plant ↔ Tag plant_tags = db.Table( 'plant_tags', db.metadata, db.Column('plant_id', db.Integer, db.ForeignKey('plant.id'), primary_key=True), db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'), primary_key=True), extend_existing=True ) class Tag(db.Model): __tablename__ = 'tag' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128), unique=True, nullable=False) class PlantCommonName(db.Model): __tablename__ = 'plant_common_name' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128), unique=True, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) scientific_names = db.relationship( 'plugins.plant.models.PlantScientificName', backref=db.backref('common', lazy='joined'), lazy=True, cascade='all, delete-orphan' ) class PlantScientificName(db.Model): __tablename__ = 'plant_scientific_name' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(256), unique=True, nullable=False) common_id = db.Column(db.Integer, db.ForeignKey('plant_common_name.id'), nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) class PlantOwnershipLog(db.Model): __tablename__ = 'plant_ownership_log' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) plant_id = db.Column(db.Integer, db.ForeignKey('plant.id'), nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) date_acquired = db.Column(db.DateTime, default=datetime.utcnow) transferred = db.Column(db.Boolean, default=False, nullable=False) is_verified = db.Column(db.Boolean, default=False, nullable=False) user = db.relationship( 'plugins.auth.models.User', backref='ownership_logs', lazy=True ) class Plant(db.Model): __tablename__ = 'plant' __table_args__ = {'extend_existing': True} id = db.Column(db.Integer, primary_key=True) uuid = db.Column( db.String(36), default=lambda: str(uuid_lib.uuid4()), unique=True, nullable=False ) custom_slug = db.Column(db.String(255), unique=True, nullable=True) owner_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) common_id = db.Column(db.Integer, db.ForeignKey('plant_common_name.id'), nullable=False) scientific_id = db.Column(db.Integer, db.ForeignKey('plant_scientific_name.id'), nullable=False) mother_uuid = db.Column(db.String(36), db.ForeignKey('plant.uuid'), nullable=True) plant_type = db.Column(db.String(50), nullable=False) notes = db.Column(db.Text, nullable=True) vendor_name = db.Column(db.String(255), nullable=True) price = db.Column(db.Numeric(10, 2), nullable=True) is_active = db.Column(db.Boolean, default=True, nullable=False) featured_media_id = db.Column(db.Integer, db.ForeignKey('media.id'), nullable=True) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column( db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow ) data_verified = db.Column(db.Boolean, default=False, nullable=False) # ↔ Media upload gallery media_items = db.relationship( 'plugins.media.models.Media', back_populates='plant', lazy='select', # ← this is the fix cascade='all, delete-orphan', foreign_keys='plugins.media.models.Media.plant_id' ) @property def media(self): return self.media_items # already a list when lazy='select' # the one you see on the detail page featured_media = db.relationship( 'plugins.media.models.Media', foreign_keys=[featured_media_id], uselist=False ) # ↔ GrowLog instances for this plant updates = db.relationship( 'plugins.growlog.models.GrowLog', backref='plant', lazy=True, cascade='all, delete-orphan' ) # tagging tags = db.relationship( Tag, secondary=plant_tags, backref='plants', lazy='dynamic' ) common_name = db.relationship( PlantCommonName, backref=db.backref('plants', lazy='dynamic'), lazy=True ) scientific_name = db.relationship( PlantScientificName, backref=db.backref('plants', lazy='dynamic'), lazy=True ) ownership_logs = db.relationship( PlantOwnershipLog, backref='plant', lazy=True, cascade='all, delete-orphan' ) def __repr__(self): return f""