<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      Fork me on GitHub

      python 之路,Day11 - sqlalchemy ORM

       

      本節內容

      1. ORM介紹
      2. sqlalchemy安裝
      3. sqlalchemy基本使用
      4. 多外鍵關聯
      5. 多對多關系
      6. 表結構設計作業

       

      1. ORM介紹

      orm英文全稱object relational mapping,就是對象映射關系程序,簡單來說我們類似python這種面向對象的程序來說一切皆對象,但是我們使用的數據庫卻都是關系型的,為了保證一致的使用習慣,通過orm將編程語言的對象模型和數據庫的關系模型建立映射關系,這樣我們在使用編程語言對數據庫進行操作的時候可以直接使用編程語言的對象模型進行操作就可以了,而不用直接使用sql語言。

      orm的優點:

      1. 隱藏了數據訪問細節,“封閉”的通用數據庫交互,ORM的核心。他使得我們的通用數據庫交互變得簡單易行,并且完全不用考慮該死的SQL語句。快速開發,由此而來。
      2. ORM使我們構造固化數據結構變得簡單易行。

      缺點:

      1. 無可避免的,自動化意味著映射和關聯管理,代價是犧牲性能(早期,這是所有不喜歡ORM人的共同點)。現在的各種ORM框架都在嘗試使用各種方法來減輕這塊(LazyLoad,Cache),效果還是很顯著的。

       

      2. sqlalchemy安裝

      在Python中,最有名的ORM框架是SQLAlchemy。用戶包括openstack\Dropbox等知名公司或應用,主要用戶列表http://www.sqlalchemy.org/organizations.html#openstack

      Dialect用于和數據API進行交流,根據配置文件的不同調用不同的數據庫API,從而實現對數據庫的操作,如:

       
      MySQL-Python
          mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
        
      pymysql
          mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
        
      MySQL-Connector
          mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
        
      cx_Oracle
          oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
        
      更多詳見:http://docs.sqlalchemy.org/en/latest/dialects/index.html
      

        

      安裝sqlalchemy

      pip install SQLAlchemy

      pip install pymysql #由于mysqldb依然不支持py3,所以這里我們用pymysql與sqlalchemy交互

       

      3.sqlalchemy基本使用

      下面就開始讓你見證orm的nb之處,盤古開天劈地之前,我們創建一個表是這樣的

      CREATE TABLE user (
      	id INTEGER NOT NULL AUTO_INCREMENT, 
      	name VARCHAR(32), 
      	password VARCHAR(64), 
      	PRIMARY KEY (id)
      )
      

      這只是最簡單的sql表,如果再加上外鍵關聯什么的,一般程序員的腦容量是記不住那些sql語句的,于是有了orm,實現上面同樣的功能,代碼如下

      import sqlalchemy
      from sqlalchemy import create_engine
      from sqlalchemy.ext.declarative import declarative_base
      from sqlalchemy import Column, Integer, String
      
      engine = create_engine("mysql+pymysql://root:alex3714@localhost/testdb",
                                          encoding='utf-8', echo=True)
      
      
      Base = declarative_base() #生成orm基類
      
      class User(Base):
          __tablename__ = 'user' #表名
          id = Column(Integer, primary_key=True)
          name = Column(String(32))
          password = Column(String(64))
      
      Base.metadata.create_all(engine) #創建表結構

      你說,娘那個腚的,并沒有感覺代碼量變少啊,呵呵, 孩子莫猴急,好戲在后面

      Lazy Connecting
      The Engine, when first returned by create_engine(), has not actually tried to connect to the database yet; that happens only the first time it is asked to perform a task against the database.  

      除上面的創建之外,還有一種創建表的方式,雖不常用,但還是看看吧

      from sqlalchemy import Table, MetaData, Column, Integer, String, ForeignKey
      from sqlalchemy.orm import mapper
      
      metadata = MetaData()
      
      user = Table('user', metadata,
                  Column('id', Integer, primary_key=True),
                  Column('name', String(50)),
                  Column('fullname', String(50)),
                  Column('password', String(12))
              )
      
      class User(object):
          def __init__(self, name, fullname, password):
              self.name = name
              self.fullname = fullname
              self.password = password
      
      mapper(User, user) #the table metadata is created separately with the Table construct, then associated with the User class via the mapper() function
      

      事實上,我們用第一種方式創建的表就是基于第2種方式的再封裝。

       

        

      最基本的表我們創建好了,那我們開始用orm創建一條數據試試

      Session_class = sessionmaker(bind=engine) #創建與數據庫的會話session class ,注意,這里返回給session的是個class,不是實例
      Session = Session_class() #生成session實例
      
      
      user_obj = User(name="alex",password="alex3714") #生成你要創建的數據對象
      print(user_obj.name,user_obj.id)  #此時還沒創建對象呢,不信你打印一下id發現還是None
      
      Session.add(user_obj) #把要創建的數據對象添加到這個session里, 一會統一創建
      print(user_obj.name,user_obj.id) #此時也依然還沒創建
      
      Session.commit() #現此才統一提交,創建數據
      

      我擦,寫這么多代碼才創建一條數據,你表示太tm的費勁了,正要轉身離開,我拉住你的手不放開,高潮還沒到。。

      查詢

      my_user = Session.query(User).filter_by(name="alex").first()
      print(my_user)
      

      此時你看到的輸出是這樣的應該

      <__main__.User object at 0x105b4ba90>
      

      我擦,這是什么?這就是你要的數據呀, 只不過sqlalchemy幫你把返回的數據映射成一個對象啦,這樣你調用每個字段就可以跟調用對象屬性一樣啦,like this..

      print(my_user.id,my_user.name,my_user.password)
      
      輸出
      1 alex alex3714

      不過剛才上面的顯示的內存對象對址你是沒辦法分清返回的是什么數據的,除非打印具體字段看一下,如果想讓它變的可讀,只需在定義表的類下面加上這樣的代碼

          def __repr__(self):
              return "<User(name='%s',  password='%s')>" % (
                  self.name, self.password)
      

        

      修改

      my_user = Session.query(User).filter_by(name="alex").first()
      
      my_user.name = "Alex Li"
      
      Session.commit()
      

      回滾

      my_user = Session.query(User).filter_by(id=1).first()
      my_user.name = "Jack"
      
      
      fake_user = User(name='Rain', password='12345')
      Session.add(fake_user)
      
      print(Session.query(User).filter(User.name.in_(['Jack','rain'])).all() )  #這時看session里有你剛添加和修改的數據
      
      Session.rollback() #此時你rollback一下
      
      print(Session.query(User).filter(User.name.in_(['Jack','rain'])).all() ) #再查就發現剛才添加的數據沒有了。
      
      # Session
      # Session.commit()
      

        

      獲取所有數據

      print(Session.query(User.name,User.id).all() )
      

       

      多條件查詢

      objs = Session.query(User).filter(User.id>0).filter(User.id<7).all()
      

      上面2個filter的關系相當于 user.id >1 AND user.id <7 的效果

      統計和分組

      Session.query(User).filter(User.name.like("Ra%")).count()
      

      分組

      from sqlalchemy import func
      print(Session.query(func.count(User.name),User.name).group_by(User.name).all() )
      

      相當于原生sql為

      SELECT count(user.name) AS count_1, user.name AS user_name 
      FROM user GROUP BY user.name
      

      輸出為

      [(1, 'Jack'), (2, 'Rain')]

       

      外鍵關聯

      我們創建一個addresses表,跟user表關聯

      from sqlalchemy import ForeignKey
      from sqlalchemy.orm import relationship
      
      class Address(Base):
          __tablename__ = 'addresses'
          id = Column(Integer, primary_key=True)
          email_address = Column(String(32), nullable=False)
          user_id = Column(Integer, ForeignKey('user.id'))
      
          user = relationship("User", backref="addresses") #這個nb,允許你在user表里通過backref字段反向查出所有它在addresses表里的關聯項
      
          def __repr__(self):
              return "<Address(email_address='%s')>" % self.email_address
      

      The relationship.back_populates parameter is a newer version of a very common SQLAlchemy feature calledrelationship.backref. The relationship.backref parameter hasn’t gone anywhere and will always remain available! The relationship.back_populates is the same thing, except a little more verbose and easier to manipulate. For an overview of the entire topic, see the section Linking Relationships with Backref.  

        

      表創建好后,我們可以這樣反查試試

      obj = Session.query(User).first()
      for i in obj.addresses: #通過user對象反查關聯的addresses記錄
          print(i)
      
      addr_obj = Session.query(Address).first()
      print(addr_obj.user.name)  #在addr_obj里直接查關聯的user表
      

      創建關聯對象

      obj = Session.query(User).filter(User.name=='rain').all()[0]
      print(obj.addresses)
      
      obj.addresses = [Address(email_address="r1@126.com"), #添加關聯對象
                       Address(email_address="r2@126.com")]
      
      
      Session.commit()
      

       

       

      常用查詢語法

      Common Filter Operators

      Here’s a rundown of some of the most common operators used in filter():

      • equals:

             query.filter(User.name == 'ed')
        
      • not equals:

             query.filter(User.name != 'ed')
        
      • LIKE:

        query.filter(User.name.like('%ed%'))

      • IN:

      • NOT IN:
        query.filter(~User.name.in_(['ed', 'wendy', 'jack']))

      • IS NULL:

      • IS NOT NULL:

      • AND:
        2.1. ObjectRelationalTutorial 17

      query.filter(User.name.in_(['ed', 'wendy', 'jack']))
      
      # works with query objects too:
      

      query.filter(User.name.in_( session.query(User.name).filter(User.name.like('%ed%'))

      ))

      query.filter(User.name == None)
      
      # alternatively, if pep8/linters are a concern
      
      query.filter(User.name.is_(None))
      
      query.filter(User.name != None)
      
      # alternatively, if pep8/linters are a concern
      
      query.filter(User.name.isnot(None))
      

      SQLAlchemy Documentation, Release 1.1.0b1

      # use and_()

      from sqlalchemy import and_
      query.filter(and_(User.name == 'ed', User.fullname == 'Ed Jones'))

      # or send multiple expressions to .filter()
      
      query.filter(User.name == 'ed', User.fullname == 'Ed Jones')
      
      # or chain multiple filter()/filter_by() calls
      
      query.filter(User.name == 'ed').filter(User.fullname == 'Ed Jones')
      

      Note: Makesureyouuseand_()andnotthePythonandoperator! ? OR:

      Note: Makesureyouuseor_()andnotthePythonoroperator! ? MATCH:

      query.filter(User.name.match('wendy'))
      Note: match() uses a database-specific MATCH or CONTAINS f 

       

        

      4.多外鍵關聯

      One of the most common situations to deal with is when there are more than one foreign key path between two tables.

      Consider a Customer class that contains two foreign keys to an Address class:

      下表中,Customer表有2個字段都關聯了Address表 

      from sqlalchemy import Integer, ForeignKey, String, Column
      from sqlalchemy.ext.declarative import declarative_base
      from sqlalchemy.orm import relationship
      
      Base = declarative_base()
      
      class Customer(Base):
          __tablename__ = 'customer'
          id = Column(Integer, primary_key=True)
          name = Column(String)
      
          billing_address_id = Column(Integer, ForeignKey("address.id")) 
          shipping_address_id = Column(Integer, ForeignKey("address.id"))
      
          billing_address = relationship("Address")  
          shipping_address = relationship("Address")
      
      class Address(Base):
          __tablename__ = 'address'
          id = Column(Integer, primary_key=True)
          street = Column(String)
          city = Column(String)
          state = Column(String)
      

      創建表結構是沒有問題的,但你Address表中插入數據時會報下面的錯

      sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join
      condition between parent/child tables on relationship
      Customer.billing_address - there are multiple foreign key
      paths linking the tables.  Specify the 'foreign_keys' argument,
      providing a list of those columns which should be
      counted as containing a foreign key reference to the parent table.
      

      解決辦法如下

      class Customer(Base):
          __tablename__ = 'customer'
          id = Column(Integer, primary_key=True)
          name = Column(String)
      
          billing_address_id = Column(Integer, ForeignKey("address.id"))
          shipping_address_id = Column(Integer, ForeignKey("address.id"))
      
          billing_address = relationship("Address", foreign_keys=[billing_address_id])
          shipping_address = relationship("Address", foreign_keys=[shipping_address_id])
      

      這樣sqlachemy就能分清哪個外鍵是對應哪個字段了

        

      5.多對多關系

      現在來設計一個能描述“圖書”與“作者”的關系的表結構,需求是

      1. 一本書可以有好幾個作者一起出版
      2. 一個作者可以寫好幾本書

      此時你會發現,用之前學的外鍵好像沒辦法實現上面的需求了,因為

      當然你更不可以像下面這樣干,因為這樣就你就相當于有多條書的記錄了,太low b了,改書名還得都改。。。

       

      那怎么辦呢? 此時,我們可以再搞出一張中間表,就可以了

      這樣就相當于通過book_m2m_author表完成了book表和author表之前的多對多關聯

      用orm如何表示呢?

      #一本書可以有多個作者,一個作者又可以出版多本書
      
      
      from sqlalchemy import Table, Column, Integer,String,DATE, ForeignKey
      from sqlalchemy.orm import relationship
      from sqlalchemy.ext.declarative import declarative_base
      from sqlalchemy import create_engine
      from sqlalchemy.orm import sessionmaker
      
      
      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(64))
          pub_date = Column(DATE)
          authors = relationship('Author',secondary=book_m2m_author,backref='books')
      
          def __repr__(self):
              return self.name
      
      class Author(Base):
          __tablename__ = 'authors'
          id = Column(Integer, primary_key=True)
          name = Column(String(32))
      
          def __repr__(self):
              return self.name
      orm 多對多

       

      接下來創建幾本書和作者

      Session_class = sessionmaker(bind=engine) #創建與數據庫的會話session class ,注意,這里返回給session的是個class,不是實例
      s = Session_class() #生成session實例
      
      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()
      

      此時,手動連上mysql,分別查看這3張表,你會發現,book_m2m_author中自動創建了多條紀錄用來連接book和author表

      mysql> select * from books;
      +----+------------------+----------+
      | id | name             | pub_date |
      +----+------------------+----------+
      |  1 | 跟Alex學Python   | NULL     |
      |  2 | 跟Alex學把妹     | NULL     |
      |  3 | 跟Alex學裝逼     | NULL     |
      |  4 | 跟Alex學開車     | NULL     |
      +----+------------------+----------+
      4 rows in set (0.00 sec)
      
      mysql> select * from authors;
      +----+------+
      | id | name |
      +----+------+
      | 10 | Alex |
      | 11 | Jack |
      | 12 | Rain |
      +----+------+
      3 rows in set (0.00 sec)
      
      mysql> select * from book_m2m_author;
      +---------+-----------+
      | book_id | author_id |
      +---------+-----------+
      |       2 |        10 |
      |       2 |        11 |
      |       2 |        12 |
      |       1 |        10 |
      |       1 |        11 |
      +---------+-----------+
      5 rows in set (0.00 sec)
      

       

      此時,我們去用orm查一下數據

      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)
      s.commit()
      

      輸出如下

      --------通過書表查關聯的作者---------
      跟Alex學Python [Alex, Jack]
      --------通過作者表查關聯的書---------
      Alex [跟Alex學把妹, 跟Alex學Python]
      

      牛逼了我的哥!!完善實現多對多  

        

      多對多刪除

      刪除數據時不用管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) #從一本書里刪除一個作者
      s.commit()
      

      直接刪除作者 

      刪除作者時,會把這個作者跟所有書的關聯關系數據也自動刪除

      author_obj =s.query(Author).filter_by(name="Alex").first()
      # print(author_obj.name , author_obj.books)
      s.delete(author_obj)
      s.commit()
      

        

      處理中文

      sqlalchemy設置編碼字符集一定要在數據庫訪問的URL上增加charset=utf8,否則數據庫的連接就不是utf8的編碼格式

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

       

       

      6.本節作業

      主題:學員管理系統

      需求:

      • 用戶角色,講師\學員, 用戶登陸后根據角色不同,能做的事情不同,分別如下
      • 講師視圖
        1.   管理班級,可創建班級,根據學員qq號把學員加入班級
        2.   可創建指定班級的上課紀錄,注意一節上課紀錄對應多條學員的上課紀錄, 即每節課都有整班學員上, 為了紀錄每位學員的學習成績,需在創建每節上課紀錄是,同時         為這個班的每位學員創建一條上課紀錄
        3.   為學員批改成績, 一條一條的手動修改成績
      • 學員視圖
      1. 提交作業
      2. 查看作業成績
      3. 一個學員可以同時屬于多個班級,就像報了Linux的同時也可以報名Python一樣, 所以提交作業時需先選擇班級,再選擇具體上課的節數
      4. 附加:學員可以查看自己的班級成績排名

        

       

       

       

       

        

       

        

        

        

       

        

        

       

        

        

        

       

        

      posted @ 2016-10-19 18:35  金角大王  閱讀(22465)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 国产精品高清一区二区三区不卡| 午夜精品亚洲一区二区三区| 国产最新进精品视频| 马边| 99麻豆久久精品一区二区| 精品国产成人国产在线观看| 大地资源网第二页免费观看| 极品无码国模国产在线观看| 综合久久av一区二区三区| 日本中文字幕不卡在线一区二区| 亚洲精品国产av成拍色拍个| 久久亚洲国产成人精品性色| 国产深夜福利视频在线| 亚洲精品自拍视频在线看| 五月综合网亚洲乱妇久久| 精品无码国产一区二区三区AV| 久久碰国产一区二区三区| 亚洲欧美一区二区三区图片| 亚洲成人高清av在线| 日韩精品二区三区四区| 久久天天躁夜夜躁狠狠85| 美女内射福利大全在线看| 亚洲一区二区三区自拍高清 | 一个色综合色综合色综合| 欧美人人妻人人澡人人尤物| 18岁日韩内射颜射午夜久久成人 | 欧美日韩一区二区三区视频播放| 航空| 国产精品毛片av999999| 亚洲熟女乱色一区二区三区 | 婷婷色综合成人成人网小说 | 国产精品一码二码三码四码| 亚洲欧美激情在线一区| 绯色蜜臀av一区二区不卡| 亚洲国产精品日韩在线| 苏尼特左旗| 国产成人亚洲精品狼色在线| 男女扒开双腿猛进入爽爽免费看| 中国CHINA体内裑精亚洲日本| av日韩在线一区二区三区| 超碰伊人久久大香线蕉综合|