DecisionTree/models.py

114 lines
4.4 KiB
Python

from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
from flask_dance.consumer.storage.sqla import OAuthConsumerMixin
db = SQLAlchemy()
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password_hash = db.Column(db.String(128))
is_admin = db.Column(db.Boolean, default=False)
# New field to track if user was created via OAuth
is_oauth_user = db.Column(db.Boolean, default=False)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
class OAuth(OAuthConsumerMixin, db.Model):
user_id = db.Column(db.Integer, db.ForeignKey(User.id))
user = db.relationship(User)
class NodeImage(db.Model):
id = db.Column(db.Integer, primary_key=True)
node_id = db.Column(db.Integer, db.ForeignKey('node.id'), nullable=False)
image_url = db.Column(db.String(500), nullable=False)
caption = db.Column(db.String(200), nullable=True)
display_order = db.Column(db.Integer, default=0)
# Relationship back to the node
node = db.relationship('Node', backref=db.backref('images', cascade='all, delete-orphan'))
class Node(db.Model):
id = db.Column(db.Integer, primary_key=True)
question = db.Column(db.String(500), nullable=False)
content = db.Column(db.Text, nullable=True)
is_terminal = db.Column(db.Boolean, default=False)
# Keep single image_url for backward compatibility
image_url = db.Column(db.String(500), nullable=True)
youtube_url = db.Column(db.String(500), nullable=True)
# Relationships
yes_node_id = db.Column(db.Integer, db.ForeignKey('node.id'), nullable=True)
no_node_id = db.Column(db.Integer, db.ForeignKey('node.id'), nullable=True)
yes_node = db.relationship('Node', foreign_keys=[yes_node_id], remote_side=[id], backref='yes_parent', uselist=False)
no_node = db.relationship('Node', foreign_keys=[no_node_id], remote_side=[id], backref='no_parent', uselist=False)
@property
def youtube_embed_url(self):
"""Convert YouTube URL to embed URL"""
if not self.youtube_url:
return None
import re
from urllib.parse import urlparse, parse_qs
# Extract video ID from various YouTube URL formats
video_id = None
# youtube.com/watch?v=VIDEO_ID format
if 'youtube.com/watch' in self.youtube_url:
parsed_url = urlparse(self.youtube_url)
video_id = parse_qs(parsed_url.query).get('v', [None])[0]
# youtu.be/VIDEO_ID format
elif 'youtu.be/' in self.youtube_url:
video_id = self.youtube_url.split('youtu.be/')[1].split('?')[0]
if video_id:
return f"https://www.youtube.com/embed/{video_id}"
return None
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
thumbnail = db.Column(db.String(200)) # URL or file path to the thumbnail image
description = db.Column(db.Text) # Add this line for product description
root_node_id = db.Column(db.Integer, db.ForeignKey('node.id'))
root_node = db.relationship("Node", foreign_keys=[root_node_id])
class SiteConfig(db.Model):
id = db.Column(db.Integer, primary_key=True)
key = db.Column(db.String(64), unique=True, nullable=False)
value = db.Column(db.String(255), nullable=True)
description = db.Column(db.String(255), nullable=True)
@classmethod
def get_setting(cls, key, default=None):
setting = cls.query.filter_by(key=key).first()
if setting:
return setting.value
return default
@classmethod
def set_setting(cls, key, value, description=None):
setting = cls.query.filter_by(key=key).first()
if setting:
setting.value = value
if description:
setting.description = description
else:
setting = cls(key=key, value=value, description=description)
db.session.add(setting)
db.session.commit()
return setting