class User(db.Model): __tablename__ = 'ods_p1_User' id = db.Column(db.Integer, primary_key=True) nickname = db.Column(db.String(64), index=True, unique=True) email = db.Column(db.String(120), index=True, unique=True) posts = db.relationship('Post', backref='author', lazy='dynamic') #db.relationship 字段。这并不是一个实际的数据库字段,因此是不会出现在上面的图中。对于一个一对多的关系,db.relationship 字段通常是定义在“一”这一边。在这种关系下 about_me = db.Column(db.String(140)) last_seen = db.Column(db.DateTime) followed = db.relationship('User', secondary=followers, primaryjoin=(followers.c.follower_id == id), secondaryjoin=(followers.c.followed_id == id), backref=db.backref('followers', lazy='dynamic'), lazy='dynamic') @property def is_authenticated(self): #is_authenticated 方法有一个具有迷惑性的名称。一般而言,这个方法应该只返回 True,除非表示用户的对象因为某些原因不允许被认证。 return True @property def is_active(self): #is_active 方法应该返回 True,除非是用户是无效的,比如因为他们的账号是被禁止。 return True @property def is_anonymous(self): #is_anonymous 方法应该返回 True,如果是匿名的用户不允许登录系统。 return False def get_id(self): #get_id 方法应该返回一个用户唯一的标识符 return str(self.id) def follow(self, user): if not self.is_following(user): self.followed.append(user) return self def unfollow(self, user): if self.is_following(user): self.followed.remove(user) return self def is_following(self, user): return self.followed.filter( followers.c.followed_id == user.id).count() > 0 def __repr__(self): #__repr__ 方法告诉 Python 如何打印这个类的对象。我们将用它来调试。 return '<User %r>' % (self.nickname)
def many_to_many(self): ''' 多对多关系会在两个类之间增加一个关联表。 这个关联的表在 relationship() 方法中通过 secondary 参数来表示。 所以这个 ForeignKey 指令会使用链接来定位到远程的表: many to many 的关系仍然是由 db.relationship() 来定义 seconddary(次级):会告知 SQLAlchemy 该 many to many 的关联保存在 posts_tags 表中 backref:声明表之间的关系是双向,帮助手册 help(db.backref)。需要注意的是:在 one to many 中的 backref 是一个普通的对象,而在 many to many 中的 backref 是一个 List 对象 NOTE 1:实际上 db.Table 对象对数据库的操作比 db.Model 更底层一些。后者是基于前者来提供的一种对象化包装, 表示数据库中的一条记录。 posts_tags 表对象之所以使用 db.Table 不使用 db.Model 来定义,是因为我们不需要对 posts_tags (self.name)进行直接的操作(不需要对象化),posts_tags 代表了两张表之间的关联,会由数据库自身来 进行处理。 NOTE 2: posts_tags 的声明定义最好在 Post 和 Tag 之前。 NOTE 3: 没添加一个 models class 都要记得在 manage.py 中导入并返回,方便之后的调试,这里就不作重复了。 :return: ''' followed = db.relationship( 'User', secondary=followers, primaryjoin=(followers.c.follower_id == id), secondaryjoin=(followers.c.followed_id == id), backref=db.backref('followers', lazy='dynamic'), lazy='dynamic') '''
class Post(db.Model): """Represents Proected posts.""" __tablename__ = 'posts' id = db.Column(db.String(45), primary_key=True) title = db.Column(db.String(255)) text = db.Column(db.Text()) publish_date = db.Column(db.DateTime) # Set the foreign key for Post user_id = db.Column(db.String(45), db.ForeignKey('users.id')) # Establish contact with Comment's ForeignKey: post_id comments = db.relationship('Comment', backref='posts', lazy='dynamic') # many to many: posts <==> tags tags = db.relationship('Tag', secondary=posts_tags, backref=db.backref('posts', lazy='dynamic')) def __init__(self, title): self.title = title def __repr__(self): return "<Model Post `{}`>".format(self.title)
def one_to_many(self): ''' db.relationsformat(self.username)hip: 会在 SQLAlchemy 中创建一个虚拟的列, 该列会与 Post.user_id (db.ForeignKey) 建立联系。这一切都交由 SQLAlchemy 自身管理。 backref:用于指定表之间的双向关系,如果在一对多的关系中建立双向的关系,这样的话在对方看来这就是一个多对一的关系 lazy:指定 SQLAlchemy 加载关联对象的方式。 lazy=subquery: 会在加载 Post 对象后,将与 Post 相关联的对象全部加载,这样就可以减少 Query 的动作,也就是减少了 对 DB 的 I/O 操作。但可能会返回大量不被使用的数据,会影响效率。 lazy=dynamic: 只有被使用时,对象才会被加载,并且返回式会进行过滤,如果现在或将来需要返回的数据量很大, 建议使用这种方式。Post 就属于这种对象。 :return: Query 对象 ''' posts = db.relationship('Post', backref='users', lazy='dynamic')
class User(db.Model): """Represents Proected users.""" # Set the name for table __tablename__ = 'users' id = db.Column(db.String(45), primary_key=True) username = db.Column(db.String(255)) password = db.Column(db.String(255)) posts = db.relationship('Post', backref='users', lazy='dynamic') def __init__(self, id, username, password): self.id = id self.username = username self.password = password def __repr__(self): """Define the string format for instance of User.""" return "<Model User `{}`>".format(self.username)