• python学习笔记之paramiko和sqlalchemy (第九天)


    参考银角大王 :http://www.cnblogs.com/wupeiqi/articles/5095821.html

                          http://www.cnblogs.com/wupeiqi/articles/5713330.html(pymysql模块)

          金角大王:http://www.cnblogs.com/alex3714/articles/5950372.html(python mysql

                         

                         http://www.cnblogs.com/alex3714/articles/5978329.html(sqlalchemy ORM

    一、Python的paramiko模块,该模块机遇SSH用于连接远程服务器并执行相关操作

    1、SSHClient

    用于连接远程服务器并执行基本命令

    基于用户名密码连接:

    import paramiko
    
    ssh = paramiko.SSHClient()
    # 允许连接不在know_hosts文件中的主机
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    ssh.connect(hostname='192.168.4.*',port=22,username='ubuntu',password='******')
    
    stdin,stdout,stderr = ssh.exec_command('df -Th')
    
    for result in stdout.readlines():
    #result = list(filter(lambda x:x is not None,[stdout.read(),stderr.read()]))[0]
       print(result,end='')
    
    ssh.close()
    
    transport = paramiko.Transport('192.168.4.*',22)
    transport.connect(username='ubuntu',password='*******')
    
    
    ssh1 = paramiko.SSHClient()
    ssh1._transport = transport
    stdin,stdout,stderr = ssh1.exec_command('ls -l')
    
    #result1 = list(filter(lambda x:x is not None,[stdout.read(),stderr.read()]))
    
    for result1 in stdout.readlines():
    #result = list(filter(lambda x:x is not None,[stdout.read(),stderr.read()]))[0]
       print(result1,end='')
    
    transport.close
    基于密码

    基于密钥连接:

    import paramiko
    
    private_key = paramiko.RSAKey.from_private_key_file('/home/ubuntu/.ssh/id_rsa')
    
    ssh = paramiko.SSHClient()
    
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    ssh.connect(hostname='192.168.4.*',port=22,username='ubuntu',pkey=private_key)
    
    stdin,stdout,stderr = ssh.exec_command('df -Th')
    
    
    result = list(filter(lambda x:x is not None,[stdout.read(),stderr.read()]))[0]
    print(result)
    
    ssh.close()
    
    transport = paramiko.Transport('192.168.4.*',22)
    transport.connect(username='ubuntu',pkey=private_key)
    
    
    ssh1 = paramiko.SSHClient()
    ssh1._transport = transport
    stdin,stdout,stderr = ssh1.exec_command('ls -l')
    
    result1 = list(filter(lambda x:x is not None,[stdout.read(),stderr.read()]))
    
    print(result1)
    transport.close
    基于密钥

    基于密钥字符串:

    import paramiko
    from io import StringIO
    
    private_str = """-----BEGIN RSA PRIVATE KEY-----
    MIIEpQIBAAKCAQEAzbQ+3wA47CEdTCSOiHL38PC4vckze2u/JXiw66uiQMsp9sDX
    CP6I4QppLaGqG1s1SjZf7H0sb7jNz7LqRZe24Scnum1Cm0YhBtVLSfy454Ugh7ec
    uHD/hM6EbKHm10jdZrd4rJezvSqJkpsc/T2MSbiYWz0I2dKb4sYbJlDB6CPtBoiZ
    8mmSadekr67SsmygYpigBWrGyjcPJa1xpaY/dqXZkByGFBY/j4Ipm792T3ilTXd1
    U1q0xa/+Axkv1doqEBAzqIukc56alSwvpPyWkTj7uH17BGIaAxjHVQM6BdWGiKbr
    AffDQuvZcOeHD/IKVY3qwU7i7kC0fjXkKj3+OwIDAQABAoIBAQCfwYa6hl+u86Df
    S9zul+t70liH/MTg67NOFMfCoE+o5qA2pVncAGKp8/3vlIiaKmHeuxAQiL6EHhCp
    aBiN59/+SPyPyt9Z3EM2HV0VnxKzrC6xeKZckFXB/OnXvH2dYVehuIgd8suC9JBX
    reP7wVs8vgKFiYdgNDMhEh5vyXRvJmMpwEF9T8h3BDA4Dzq/algGheX+fAPbsIV8
    lTymzf3y4BZN+F1vBBUidV5IaDvHO8ojwvJmVw0PM/DIfssbruzqw96czeIhv2SN
    1TK56aWHWBClq7CRVrSF8wHVcAuKFl4Bldm6OneT4fZFTmsdFgbT7N+Xd3d9T7O7
    OhDgkctBAoGBAOjP/BAUv5dI/HBMyPEPrKa27nitlGn+SVXURdLNEIRAL5ayb0FD
    xcHG3DoJ68DLTX/E4okyySRERqT8MF3cfpuFC69rzN5ZPvlyLll8iH/y7r7jMsPi
    g0T8xN17cRgk3tzkpEU+RbXXZeGWvz7H/taZJ0IjRlrMVgpkX3Fhiv4RAoGBAOIx
    FGI0P5MPfZYU0fhL0ltDCbRnOmQKcgnY815dkOi6E/7lDAVKygwuVeFBnw68NhWS
    VXUMZHD6cL3PLD1nxMtnUCfjoxsgWed3I53Zr9+werQbp7uagXEkbXxC4fLAB5y2
    8+n/Gt8lM2kS270fakuENgjF1TG1dgLcHViWFluLAoGBAMLmw51u0UpEltko3xw4
    RBC5moC6yEHH2Psan22vsQEWfwCI1uzrYNYttdZ80bnwOSwa1o+HTa6n3gBnA9LA
    Mdnekv7Dn5oRWtAXj8foopmC9e4mZCxrJ/wMJH9KxU4yJ8UDQKabUF7AOZGW0vor
    EiPzyVLsFw0SfYFrsB9KSsMRAoGAAKb9lQ7rhAQOa6lhtaKaV7MIyyFlFLbG/2pF
    wWbprRIkTp7gev9tN73Gd6DV0ZgPW96RKoY/n+fI/XMkgITVF3UT0Rmh9ckRGU7J
    poHjNPTwVaaixDK83tOpESusNSQCoZwRdgJLVItp64qnYZM+njsiYMIZTExmq7lw
    yDmelOMCgYEA0zMbr8mivE+9eQ6gWL/u2Z6Dgpuzk2LZ25axvjU9rdt4lZEm1WIR
    tbfUPsVMsTEJAAUJDHQ73a0aODLMv03HVNcikiCkPg+1cfJYWqyRFVkfM7Txvqxj
    1XN5Uv6Y33j3g3xjC73qQG3uqFXPE1NKh9f0Vr4P12H8hp91JjMPITE=
    -----END RSA PRIVATE KEY-----""" 
    
    private_key = paramiko.RSAKey(file_obj=StringIO(private_str))
    
    ssh = paramiko.SSHClient()
    
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    ssh.connect(hostname='192.168.4.*',port=22,username='ubuntu',pkey=private_key)
    
    stdin,stdout,stderr = ssh.exec_command('df -Th')
    
    
    result = list(filter(lambda x:x is not None,[stdout.read(),stderr.read()]))[0]
    print(result)
    
    ssh.close()
    
    transport = paramiko.Transport('192.168.4.*',22)
    transport.connect(username='ubuntu',pkey=private_key)
    
    
    ssh1 = paramiko.SSHClient()
    ssh1._transport = transport
    stdin,stdout,stderr = ssh1.exec_command('ls -l')
    
    result1 = list(filter(lambda x:x is not None,[stdout.read(),stderr.read()]))
    
    print(result1)
    transport.close
    基于密钥字符串

    2、SFTPClient

    用于连接远程服务器并执行上传下载

    可单个文件上传、下载,亦可批量上传,下载(但无法保持目录结构)

    import paramiko,os,sys
    from stat import ST_MODE, S_ISREG, S_ISDIR, S_ISLNK
    
    # 定义一个类,表示一台远端linux主机
    class Linux(object):
        # 通过IP, 用户名,密码,超时时间初始化一个远程Linux主机
        def __init__(self, ip, username, password, timeout=30):
            self.ip = ip
            self.username = username
            self.password = password
            self.timeout = timeout
            # transport和chanel
            self.t = ''
            self.chan = ''
            # 链接失败的重试次数
            self.try_times = 3
    
        # 调用该方法连接远程主机
        def connect(self):
             pass
    
        # 断开连接
        def close(self):
            pass
    
        # 发送要执行的命令
        def send(self, cmd):
            pass
    
        # get单个文件
        def sftp_get(self, remotefile, localfile):
            t = paramiko.Transport(sock=(self.ip, 22))
            t.connect(username=self.username, password=self.password)
            sftp = paramiko.SFTPClient.from_transport(t)
            sftp.get(remotefile, localfile)
            t.close()
    
        # put单个文件
        def sftp_put(self, localfile, remotefile):
            t = paramiko.Transport(sock=(self.ip, 22))
            t.connect(username=self.username, password=self.password)
            sftp = paramiko.SFTPClient.from_transport(t)
            sftp.put(localfile, remotefile)
            t.close()
    
        # ------获取远端linux主机上指定目录及其子目录下的所有文件------
        def __get_all_files_in_remote_dir(self, sftp, remote_dir):
            # 保存所有文件的列表
            all_files = list()
    
            # 去掉路径字符串最后的字符'/',如果有的话
            if remote_dir[-1] == '/':
                remote_dir = remote_dir[0:-1]
    
            # 获取当前指定目录下的所有目录及文件,包含属性值
            files = sftp.listdir_attr(remote_dir)
            for x in files:
                # remote_dir目录中每一个文件或目录的完整路径
                print(x)
                print(x.st_mode)
                filename = remote_dir + '/' + x.filename
                # 如果是目录,则递归处理该目录,这里用到了stat库中的S_ISDIR方法,与linux中的宏的名字完全一致
                if S_ISDIR(x.st_mode):
                    all_files.extend(self.__get_all_files_in_remote_dir(sftp, filename))
                else:
                    all_files.append(filename)
            return all_files
    
        def sftp_get_dir(self, remote_dir, local_dir):
            t = paramiko.Transport(sock=(self.ip, 22))
            t.connect(username=self.username, password=self.password)
            sftp = paramiko.SFTPClient.from_transport(t)
        
            # 获取远端linux主机上指定目录及其子目录下的所有文件
            all_files = self.__get_all_files_in_remote_dir(sftp, remote_dir)
            # 依次get每一个文件
            for x in all_files:
                filename = x.split('/')[-1]
                local_filename = os.path.join(local_dir, filename)
                print('Get文件%s传输中...' % filename)
                sftp.get(x, local_filename)
    
    
     # ------获取本地指定目录及其子目录下的所有文件------
        def __get_all_files_in_local_dir(self, local_dir):
            # 保存所有文件的列表
            all_files = list()
    
            # 获取当前指定目录下的所有目录及文件,包含属性值
            files = os.listdir(local_dir)
            for x in files:
                # local_dir目录中每一个文件或目录的完整路径
                filename = os.path.join(local_dir, x)
                # 如果是目录,则递归处理该目录
                if os.path.isdir(x):
                    all_files.extend(self.__get_all_files_in_local_dir(filename))
                else:
                    all_files.append(filename)
            return all_files
    
        def sftp_put_dir(self, local_dir, remote_dir):
            t = paramiko.Transport(sock=(self.ip, 22))
            t.connect(username=self.username, password=self.password)
            sftp = paramiko.SFTPClient.from_transport(t)
    
            # 去掉路径字符穿最后的字符'/',如果有的话
            if remote_dir[-1] == '/':
                remote_dir = remote_dir[0:-1]
    
            # 获取本地指定目录及其子目录下的所有文件
            all_files = self.__get_all_files_in_local_dir(local_dir)
            # 依次put每一个文件
            for x in all_files:
                filename = os.path.split(x)[-1]
                remote_filename = remote_dir + '/' + filename
                print('Put文件%s传输中...' % filename)
                sftp.put(x, remote_filename)
    
    
    if __name__ == '__main__':
        remotefile = '/home/ubuntu/devops/currency_rate.sh' 
        localfile = '/home/ubuntu/test/currency_rate.sh' 
    
        remote_path = '/home/ubuntu/aa' 
        local_path = '/home/ubuntu/test' 
    
        host = Linux('192.168.4.*', 'ubuntu', '******')
    
        # 将远端的xxoo.txt get到本地,并保存为ooxx.txt
        #host.sftp_get(remotefile, localfile)
    
        # # 将本地的xxoo.txt put到远端,并保持为xxoo.txt
        # host.sftp_put(localfile, remotefile)
    
    
        # 将远端remote_path目录中的所有文件get到本地local_path目录
        host.sftp_get_dir(remote_path, local_path)
        # # 将本地local_path目录中的所有文件put到远端remote_path目录
        #host.sftp_put_dir(remote_path, local_path)
    批量上传下载

    二、使用pymysql模块进行mysql数据库操作:

    import pymysql

    conn = pymysql.connect(host='192.168.4.*',port=3306,
    user='hzfdt', passwd='****', db='test')
    cur = conn.cursor()
    cur.execute("USE test")

    #cur.execute("insert into students(name,sex,age,tel) values('kai','feman',36,'18069859005')")
    #conn.commit()

    cur.execute("select * from students")

    #cur.scroll(-1,mode='relative')

    #cur.scroll(2,mode='absolute')

    aa = cur.fetchall()


    cur.close()
    conn.close()

    三、sqlalchemy使用
    1、导入指定模块:

    import sqlalchemy
    from sqlalchemy import create_engine,Column,Integer,String,func
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker

    2、初始化数据库连接:
    ###初始化数据库连接:
    ###'数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名'
    engine = create_engine("mysql+pymysql://hzfdt:*****@192.168.4.208/test",encoding='utf-8',echo=False)

    ###生成orm基类
    Base = declarative_base()

    3、创建一个表:
    ###具体每个表的class定义
    class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True,autoincrement=True)
    name = Column(String(32),unique=True,nullable=False)
    password = Column(String(64),nullable=False)

    ###正常返回查询的内存对象对址,要变的可读,只需在定义表的类下面加上这样的代码
    def __repr__(self):
    return "<User(id = %d,name = %s,password = %s)>" % (self.id,self.name,self.password)

    #######################创建表#######################
    Base.metadata.create_all(engine)

    4、添加数据:
    ###创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
    Session_class = sessionmaker(bind=engine)
    
    ###生成session实例
    Session = Session_class()
    
    #######################添加数据#######################
    user_obj = User(name='zhang',password='123')
    
    ###把要创建的数据对象添加到这个session里
    Session.add(user_obj)
    
    ###提交,创建数据
    Session.commit()
    添加数据
    5、查询数据
    #######################查询数据#######################
    ###all返回是一个查询数据的列表,故需要循环
    my_user = Session.query(User).filter_by(name = "zhang").all()
    
    ###first返回
    my_user_1 = Session.query(User).filter_by(name = "zhang").first()
    
    
    ###one查询只有唯一一条的记录
    my_user_2 = Session.query(User).filter_by(name = "kai").one()
    
    '''
    ###表类中没有__repr__函数下的输出查询结果
    print(my_user)
    for user in my_user:
        print(user.id,user.name,user.password)
    
    print(my_user_1)
    print(my_user_1.id,my_user_1.name,my_user_1.password)
    
    print(my_user_2)
    print(my_user_2.id,my_user_2.name,my_user_2.password)
    '''
    
    ###输出结果如下###
    '''
    [<__main__.User object at 0x103803eb8>, <__main__.User object at 0x103803f28>, <__main__.User object at 0x103803f98>]
    5 zhang 123
    6 zhang 123
    7 zhang 123
    <__main__.User object at 0x103803eb8>
    5 zhang 123
    <__main__.User object at 0x10390d400>
    4 kai 123
    '''
    
    '''
    ###表类中有__repr__函数下的输出查询结果
    print(my_user)
    print(my_user_1)
    print(my_user_2)
    
    ###输出结果如下###
    
    [<User(id = 5,name = zhang,password = 123)>, <User(id = 6,name = zhang,password = 123)>, <User(id = 7,name = zhang,password = 123)>]
    <User(id = 5,name = zhang,password = 123)>
    <User(id = 4,name = kai,password = 123)>
    '''
    查询数据

       6、修改数据:

    #######################修改数据#######################
    my_user = Session.query(User).filter_by(name = "zhang").first()
    
    print(my_user)
    
    my_user.password = '123456'
    
    Session.commit()
    
    print(my_user)
    修改数据

      7、回滚数据:

    #######################回滚数据######################
    my_user = Session.query(User).filter_by(name = 'wang').first()
    
    my_user.name = 'zhou'
    
    fake_user = User(name = 'liu',password = 'abcd')
    Session.add(fake_user)
    ###这时看session里有你刚添加和修改的数据
    print(Session.query(User).filter(User.name.in_(['zhou','liu'])).all() )
    
    #Session.rollback()
    
    print(Session.query(User).filter(User.name.in_(['zhou','liu'])).all() )
    
    Session.commit()
    回滚数据

       8、外键关联:

    relationship进行二表关联,名字随便取
    relationship_populates二个表中的populates后面的命名必须互为对应
    relationship_backref 在关联表中定义,允许你在被关联表里通过backref字段反向查出所有它在本表里的关联项
    #!/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
    # -*- coding: utf-8 -*-
    
    import sqlalchemy
    from sqlalchemy import create_engine,Column,Integer,String,func,ForeignKey,and_
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker,relationship
    
    ###初始化数据库连接:
    ###'数据库类型+数据库驱动名称://用户名:口令@机器地址:端口号/数据库名'
    engine = create_engine("mysql+pymysql://hzfdt:******@192.168.4.208/test",encoding='utf-8',echo=False)
    
    ###生成orm基类
    Base = declarative_base()
    
    ###具体每个表的class定义
    class User(Base):
        __tablename__ = 'user'
        id = Column(Integer, primary_key=True,autoincrement=True)
        name = Column(String(32),unique=True,nullable=False)
        password = Column(String(64),nullable=False)
    
        #user_rs = relationship("Address")
        #user_list = relationship("Address",back_populates='addr')
        user_rs_backref = relationship("Address",backref="user_list_1")
        ###这个nb,允许你在user表里通过backref字段反向查出所有它在addresses表里的关联项
    
        ###正常返回查询的内存对象对址,要变的可读,只需在定义表的类下面加上这样的代码
        #def __repr__(self):
        #   return "<User(id = %d,name = %s,password = %s)>" % (self.id,self.name,self.password)
    
    class Address(Base):
        __tablename__ = 'addresses'
        id = Column(Integer, primary_key=True, autoincrement=True)
        email_address = Column(String(32), nullable=False)
        user_id = Column(Integer, ForeignKey('user.id'))
    
        #addr_rs = relationship("User")
        #addr = relationship("User",back_populates="user_list")
        addr_rs_backref = relationship("User",backref="addr_1")
    
        #def __repr__(self):
        #   return "<Address(email_address='%s')>" % self.email_address
    
    
    #######################创建表#######################
    #Base.metadata.create_all(engine)
    
    ###创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
    Session_class = sessionmaker(bind=engine)
    
    ###生成session实例
    Session = Session_class()
    
    
    
    
    #obj = Session.query(User).filter(and_(User.name=='zhang',User.id=='6')).first()
    #obj = Session.query(User).filter(User.name=='zhang',User.id=='6').first()
    #print(obj.name,obj.id)
    '''
    obj.addresses = [Address(email_address='aa@hzfdt.com'),
                     Address(email_address='bb@hzfdt.com')]
    
    Session.commit()
    print(obj.addresses)
    '''
    
    user_obj = Session.query(User).filter(User.name=='zhang').first()
    addr_obj = Session.query(Address).first()
    
    #########relationship################
    ###用relationship进行二表关联,名字随便取###
    #print(user_obj.name,user_obj.password)
    #for i in user_obj.user_rs:
    #    print(i.user_id,i.email_address)
    #print(addr_obj.addr_rs.name,addr_obj.addr_rs.id)
    '''
    结果如下:
    zhang 123456
    5 aa@qq.com
    5 bb@qq.com
    zhang 5
    '''
    #########relationship_populates################
    ###二个表中的populates后面的命名必须互为对应###
    #print(user_obj.name,user_obj.password)
    #for i in user_obj.user_list:
    #    print(i.user_id,i.email_address)
    #print(addr_obj.addr.name,addr_obj.addr.id)
    
    '''
    结果如下:
    zhang 123456
    5 aa@qq.com
    5 bb@qq.com
    zhang 5
    '''
    
    #############relationship_backref###############
    ####这个nb,允许你在user表里通过backref字段反向查出所有它在addresses表里的关联项
    print(user_obj.name,user_obj.password)
    for i in user_obj.addr_1:
        print(i.email_address)
    print(addr_obj.user_list_1.name,addr_obj.user_list_1.id)
    
    '''
    结果如下:
    zhang 123456
    aa@qq.com
    bb@qq.com
    zhang 5
    '''
    View Code

    9、多对多关系

    处理中文

    sqlalchemy设置编码字符集一定要在数据库访问的URL上增加charset=utf8,否则数据库的连接就不是utf8的编码格式

    eng = create_engine('mysql://root:root@localhost:3306/test2?charset=utf8',echo=True)

    #一本书可以有多个作者,一个作者又可以出版多本书

    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index,func,and_,Table,text,DATE
    from sqlalchemy.orm import sessionmaker, relationship
    from sqlalchemy import create_engine
    from sqlalchemy.sql import func
    
    
    engine = create_engine("mysql+pymysql://hzfdt:*****@192.168.4.x/test?charset=utf8",echo=True)
    
    ###生成orm基类
    Base = declarative_base()
    
    book_m2m_author = Table('book_m2m_author', Base.metadata,
                            Column('book_id',Integer,ForeignKey('books.id')),
                            Column('author_id',Integer,ForeignKey('authors.id')),
                            )
    
    class Book(Base):
        __tablename__ = 'books'
        id = Column(Integer,primary_key=True)
        name = Column(String(256))
        pub_date = Column(DATE)
        authors = relationship('Author',secondary=book_m2m_author,backref='books')
    
    
        def __repr__(self):
           return "the book name is %s,the pub date is %s" % (self.name,self.pub_date)
    
    class Author(Base):
        __tablename__ = 'authors'
        id = Column(Integer, primary_key=True)
        name = Column(String(256))
    
        #abc = relationship('Book', secondary=book_m2m_author, backref='auth')
    
        def __repr__(self):
            return "the author name is %s" % self.name
    
    #Base.metadata.create_all(engine)
    ###创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
    Session_class = sessionmaker(bind=engine)
    s = Session_class()
    
    ###添加数据###
    '''
    b1 = Book(name="跟Alex学Python")
    b2 = Book(name="跟Alex学把妹")
    b3 = Book(name="跟Alex学装逼")
    b4 = Book(name="跟Alex学开车")
    
    a1 = Author(name="Alex")
    a2 = Author(name="Jack")
    a3 = Author(name="Rain")
    
    b1.authors = [a1, a2]
    b2.authors = [a1, a2, a3]
    
    s.add_all([b1, b2, b3, b4, a1, a2, a3])
    
    s.commit()
    '''
    
    ###查询数据###
    print('--------通过书表查关联的作者---------')
     
    book_obj = s.query(Book).filter_by(name="跟Alex学Python").first()
    print(book_obj.name, book_obj.authors)
     
    print('--------通过作者表查关联的书---------')
    author_obj =s.query(Author).filter_by(name="Alex").first()
    print(author_obj.name , author_obj.books)
    
    ###多对多删除###
    ###删除数据时不用管boo_m2m_authors , sqlalchemy会自动帮你把对应的数据删除###
    
    #通过书删除作者
    author_obj =s.query(Author).filter_by(name="Jack").first()
    book_obj = s.query(Book).filter_by(name="跟Alex学把妹").first()
    book_obj.authors.remove(author_obj) #从一本书里删除一个作者
    
    #通过作者删除书#
    book_obj = s.query(Book).filter_by(name="跟Alex学Python").first()
    author_obj.books.remove(book_obj)  #从一个作者里删除一本书
    s.commit()
    
    
    #直接删除作者或书#
    author_obj =s.query(Author).filter_by(name="Alex").first()
    book_obj = s.query(Book).filter_by(name="跟Alex学把妹").first()
    s.delete(author_obj)
    s.delete(book_obj)
    s.commit()
    多对多举例

    10、使用sqlalchemy建立携带加密字段的ORM表

    数据库密码明文是很危险的一件事情,所以需要进行对密码进行加密。结werkzeug.security进行对用户密码加密。

    from sqlalchemy.ext.hybrid import hybrid_property
    from werkzeug.security import generate_password_hash,check_password_hash
    
    class UserProfile(Base):
        __tablename__ = 'user_profile'
        id = Column(Integer,primary_key=True,autoincrement=True)
        username = Column(String(32),unique=True,nullable=False)
        password = Column(String(256),unique=True,nullable=False)
        groups = relationship('Group',secondary=Group2UserProfile)
        bind_hosts = relationship('BindHost',secondary=BindHost2UserProfile)
        audit_logs = relationship('AuditLog')
    
    
        @hybrid_property
        def passwd(self):
            return self.password
    
        @passwd.setter
        def hash_passwd(self,plaintext):
            self.password = generate_password_hash(plaintext)
    
        def verify_passwd(self,plaintext):
            return check_password_hash(self.password,plaintext)
    密码加密

    #创建的时候还是使用password字段存入

    obj = models.UserProfile(username=key,passwd=val.get('password'))

     #直接使用方法,密码正确就会返回True

    user_obj = session.query(models.UserProfile).filter(models.UserProfile.username==username).first()

    user_obj.verify_passwd(password)

    故障排错:

    在python3.4下SQLAlchemy1.1.18下如下设置:

    @hybrid_property
    def passwd(self):
          return self.password

    @passwd.setter
    def hash_passwd(self,plaintext):
         self.password = generate_password_hash(plaintext)

    二个函数名可以不一致;但在python3.5下SQLAlchemy1.2.6环境下,函数名称一定要一样,否则会报如下错误:

    File "/usr/local/lib/python3.5/dist-packages/SQLAlchemy-1.2.6-py3.5-linux-x86_64.egg/sqlalchemy/ext/hybrid.py", line 873, in __set__
    raise AttributeError("can't set attribute")
    AttributeError: can't set attribute

  • 相关阅读:
    Delphi程序流程三(2)(while)PS:最简单的任务管理器( 组件LISTVIEW的用法 增加LISTVIEW的读取 删除)
    Delphi 编译错误信息表(转载自万一博客)
    Delphi程序流程三(1)(while)PS:顺便写了个最简单的任务管理器(包含申明API 自己申明参数为结构型API 组件LISTVIEW的用法)
    Delphi程序流程二(for)
    内核编程 warning C4273: 'PsGetProcessId' : inconsistent dll linkage
    简单的SEH处理
    【转】VC6.0各个文件说明
    【转】两篇关于__security_cookie的介绍
    完美解决 error C2220: warning treated as error
    【转】IDA 与VC 加载符号表
  • 原文地址:https://www.cnblogs.com/wushank/p/7783101.html
Copyright © 2020-2023  润新知