models.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. from flask_sqlalchemy import SQLAlchemy
  2. from flask_login import UserMixin
  3. from werkzeug.security import generate_password_hash, check_password_hash
  4. from datetime import datetime
  5. db = SQLAlchemy()
  6. # 用户与分类的关联表(用户收藏的公共分类)
  7. user_categories = db.Table('user_categories',
  8. db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
  9. db.Column('category_id', db.Integer, db.ForeignKey('category.id'))
  10. )
  11. # 用户与站点的关联表(用户收藏的公共站点)
  12. user_sites = db.Table('user_sites',
  13. db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
  14. db.Column('site_id', db.Integer, db.ForeignKey('site.id'))
  15. )
  16. class User(UserMixin, db.Model):
  17. id = db.Column(db.Integer, primary_key=True)
  18. username = db.Column(db.String(80), unique=True, nullable=False)
  19. email = db.Column(db.String(120), unique=True, nullable=False)
  20. password_hash = db.Column(db.String(200), nullable=False)
  21. is_admin = db.Column(db.Boolean, default=False)
  22. created_at = db.Column(db.DateTime, default=datetime.utcnow)
  23. # 用户自己的分类和站点
  24. categories = db.relationship('Category', backref='owner', lazy=True,
  25. foreign_keys='Category.user_id')
  26. sites = db.relationship('Site', backref='owner', lazy=True,
  27. foreign_keys='Site.user_id')
  28. # 用户收藏的公共分类和站点
  29. favorite_categories = db.relationship('Category', secondary=user_categories,
  30. backref=db.backref('favorited_by', lazy='dynamic'))
  31. favorite_sites = db.relationship('Site', secondary=user_sites,
  32. backref=db.backref('favorited_by', lazy='dynamic'))
  33. def set_password(self, password):
  34. self.password_hash = generate_password_hash(password)
  35. def check_password(self, password):
  36. return check_password_hash(self.password_hash, password)
  37. def __repr__(self):
  38. return f'<User {self.username}>'
  39. class Category(db.Model):
  40. id = db.Column(db.Integer, primary_key=True)
  41. name = db.Column(db.String(100), nullable=False)
  42. user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
  43. is_public = db.Column(db.Boolean, default=False)
  44. created_at = db.Column(db.DateTime, default=datetime.utcnow)
  45. # 关系
  46. sites = db.relationship('Site', backref='category', lazy=True, cascade="all, delete-orphan")
  47. def __repr__(self):
  48. return f'<Category {self.name}>'
  49. class Site(db.Model):
  50. id = db.Column(db.Integer, primary_key=True)
  51. name = db.Column(db.String(100), nullable=False)
  52. url = db.Column(db.String(500), nullable=False)
  53. description = db.Column(db.Text)
  54. icon = db.Column(db.String(500)) # 自动获取的favicon URL
  55. custom_icon = db.Column(db.String(500)) # 用户上传的自定义图标
  56. is_public = db.Column(db.Boolean, default=False)
  57. created_at = db.Column(db.DateTime, default=datetime.utcnow)
  58. last_visited = db.Column(db.DateTime)
  59. # 外键
  60. user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
  61. category_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=False)
  62. def __repr__(self):
  63. return f'<Site {self.name}>'