在数据库,所谓表关系,只是人为认为的添加上去的表与表之间的关系,只是逻辑上认为的关系,实际上数据库里面的表之间并没有所谓的表关系。
一对一表关系
创建Module
需要先创建对应的 Module ,这里采用之前建立好的 User 和 UserDetails。
class User(Base):
__tablename__ = 'users' #数据库中表明
id = Column(Integer,primary_key=True,autoincrement=True) #Column 用来创建表字段的一个方法
username = Column(String(12))
password = Column(String(20))
creatime = Column(DateTime,default=datetime.now)
_locked = Column(Boolean,default=False,nullable=False)
class UserDetails(Base):
__tablename__ = 'user_details'
id = Column(Integer,primary_key=True,autoincrement=True)
id_card = Column(Integer,nullable=True,unique=True)
last_login =Column(DateTime)
login_num = Column(Integer,default=0)
user_id = Column(Integer,ForeignKey('users.id'))
relationship
from sqlalchemy.orm import relationship,backref
#在UserDetails中添加如下代码
#在使用relationship的时候上面必须要有ForeignKey
userdetail = relationship('User', backref='details', uselist=False, cascade='all')
使用:
rows = session.query(User).get(2) #获得id为2的数据信息
print(rows.username)
print(rows.details)
rows = session.query(UserDetails).get(2)
print(rows.userdetail)
自动添加属性
在刚才这里, User 里面本来是没有 details 这个属性的,但是在 UserDetails 里面添加 relationship 之后,User 实例会自动加上 details 属性。
relationship
表关系是逻辑上的关系,但是 mysql 中并没有直接说明表关系的东西,外键约束是一个表现形式,外键是一种表之间的约束,可以用来表示这种关系
在SQLAlchemy里面,这个relationship代表了一对多的关系,当然我们可以通过参数改变关系,它默认是一对多的关系,而这个关系是SQLAlchemy里面的,和数据库没有关系,但是relationship是和外键一起使用的。
relationship参数分解
relationship('User', backref='details', uselist=False, cascade='all')
User: 关联的 Module;
backref: 在对应的 Module 中添加属性;
uselist: 表示 一对多 关系, 如果是一对多关系,则不需要重新赋值,如果是一对一关系,则需要赋值为 False;
cascade: 自动关系处理,就和 MySQL 中的 ON DELETE 类似;
cascade
cascade 所有的可选字符串项是:
all , 所有操作都会自动处理到关联对象上.
save-update , 关联对象自动添加到会话.
delete , 关联对象自动从会话中删除.
delete-orphan , 属性中去掉关联对象, 则会话中会自动删除关联对象.
merge , session.merge() 时会处理关联对象.
refresh-expire , session.expire() 时会处理关联对象.
expunge , session.expunge() 时会处理关联对象.
正向反向查询
分辨正向反向查询,主要看ForeignKey在哪个Module.
一对多关系
relationship默认是一对多关系,uselist=True,默认是True,因此可以省略不写。
多对多关系
创建Module
from sqlalchemy import Table
#中间表
user_article = Table('user_article',Base.metadata,
Column('user_id',Integer,ForeignKey('users.id'),primary_key=True),
Column('article_id',Integer,ForeignKey('article.id'),primary_key=True)
)
class Article(Base):
__tablename__ = 'article'
id = Column(Integer, primary_key=True, autoincrement=True)
content = Column(String(500), nullable=True)
create_time = Column(DateTime, default=datetime.now)
article_user = relationship('User', backref='article', secondary=user_article)
def __repr__(self):
return 'Article(id=%s, content=%s, creat_time=%s)' % (
self.id,
self.content,
self.create_time
)
包管理
包概念:
把很多模块放到一个文件夹里面,就可以形成一个包。包管理:
当把很多模块放在文件中时,为了方便引用包中的模块,引入了包管理。__init__.py:
在包管理中,加入此模块,则包名可以直接通过属性访问的方式,访问此模块内的对象,此模块不加上可能不会报错,但是规范是要加上,文件内容可以为空。相对路径导入:
在包管理中,可以通过 . (一个点) 和 .. (两个点)分别来导入同层和上一层的模块。引入作用:
在包中,如果包中模块要导入同一包中的其他模块,就必须使用此方法导入。使用方法:
from .module(..module) import obj (as new_name)-
引入之后的影响:
当一个模块中出现此导入方式,则该模块不能被直接运行,只能被导入。
简单的登录
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
from data.user_module import User
from tornado.options import define,options
define('port', default=8080, help='run port', type=int)
class LoginHandler(tornado.web.RequestHandler):
def get(self):
self.render('login.html')
def post(self,*args,**kwargs):
user = self.get_argument('name','')
username = User.by_name(user)
passwd = self.get_argument('password','')
print(user,username,passwd)
if username and passwd == username[0].password:
self.render('home.html',username=username)
else:
self.write('用户名或密码错误')
application = tornado.web.Application(
handlers = [
(r'/login',LoginHandler),
],
template_path = 'templates', #想要Tornado能够正确的找到html文件,需要在 Application 中指定文件的位置
debug = True #调试模式,修改后自动重启服务,不需要自动重启,生产情况下切勿开启,安全性
)
if __name__ == '__main__':
tornado.options.parse_command_line()
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
register.html
home.html
{% if username %}
欢迎用户{{username[0].username}}登录
{% else %}
你还没有登录
{% end %}