flask-day7:sqlalchemy|Column数据类型和常用参数|表间关系|1对多|1对1

SQLALchemy数据类型与参数

SQLAlchemy常用数据类型(相当于字段的数据格式):

  1. Integer:整形,映射到数据库中是int类型。

  2. Float:浮点类型,映射到数据库中是float类型。他占据的32位。

  3. Double:双精度浮点类型,映射到数据库中是double类型,占据64位。

  4. String:可变字符类型,映射到数据库中是varchar类型.

  5. Boolean:布尔类型,映射到数据库中的是tinyint类型。

  6. DECIMAL:定点类型。是专门为了解决浮点类型精度丢失的问题的。在存储钱相关的字段的时候建议大家都使用这个数据类型。并且这个类型使用的时候需要传递两个参数,第一个参数是用来标记这个字段总能能存储多少个数字,第二个参数表示小数点后有多少位。

  7. Enum:枚举类型。指定某个字段只能是枚举中指定的几个值,不能为其他值。在ORM模型中,使用Enum来作为枚举,示例代码如下:

    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        tag = Column(Enum("python",'flask','django'))
    

    在Python3中,已经内置了enum这个枚举的模块,我们也可以使用这个模块去定义相关的字段。示例代码如下:

    class TagEnum(enum.Enum):
        python = "python"
        flask = "flask"
        django = "django"
    
    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        tag = Column(Enum(TagEnum))
    
    article = Article(tag=TagEnum.flask)
    
  8. Date:存储时间,只能存储年月日。映射到数据库中是date类型。在Python代码中,可以使用datetime.date来指定。示例代码如下:

    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        create_time = Column(Date)
    
    article = Article(create_time=date(2017,10,10))
    
  9. DateTime:存储时间,可以存储年月日时分秒毫秒等。映射到数据库中也是datetime类型。在Python代码中,可以使用datetime.datetime来指定。示例代码如下:

    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        create_time = Column(DateTime)
    
    article = Article(create_time=datetime(2011,11,11,11,11,11))
    
  10. Time:存储时间,可以存储时分秒。映射到数据库中也是time类型。在Python代码中,可以使用datetime.time来至此那个。示例代码如下:

    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        create_time = Column(Time)
    
    article = Article(create_time=time(hour=11,minute=11,second=11))
    
  11. Text:存储长字符串。一般可以存储6W多个字符。如果超出了这个范围,可以使用LONGTEXT类型。映射到数据库中就是text类型。

  12. LONGTEXT:长文本类型,映射到数据库中是longtext类型。

Column常用参数:相当于对字段的主键、非空等限制

  1. primary_key:设置某个字段为主键。
  2. autoincrement:设置这个字段为自动增长的。
  3. default:设置某个字段的默认值。在发表时间这些字段上面经常用。
  4. nullable:指定某个字段是否为空。默认值是True,就是可以为空。
  5. unique:指定某个字段的值是否唯一。默认是False。
  6. onupdate:在数据更新的时候会调用这个参数指定的值或者函数。在第一次插入这条数据的时候,不会用onupdate的值,只会使用default的值。常用的就是update_time(每次更新数据的时候都要更新的值)。
  7. name:指定ORM模型中某个属性映射到表中的字段名。如果不指定,那么会使用这个属性的名字来作为字段名。如果指定了,就会使用指定的这个值作为参数。这个参数也可以当作位置参数,在第1个参数来指定。
    title = Column(String(50),name='title',nullable=False)
    title = Column('my_title',String(50),nullable=False)
    

示例:

# ---coding:utf-8----
# 文件名: create_orm.py
# @Time:2020/4/19 18:17
import enum
from datetime import datetime

from sqlalchemy import create_engine, Column, Integer, String, DECIMAL, BOOLEAN, DateTime, Enum
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.ext.declarative import declarative_base

HOSTNAME = '120.24.*.*'
PORT = '3306'
DATABASE = 'school'
USERNAME = 'python'
PASSWORD = '*'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URI)

Base = declarative_base(engine)
class tagEnum(enum.Enum):
    China = "国内"
    Europe = "欧洲"
    America = "美国"
    Other = "其他"
class Article(Base):
    __tablename__ = "article"
    id = Column(Integer,primary_key=True,autoincrement=True)
    title = Column(String(100),name="title_a",nullable=True,unique=True)
    price = Column(DECIMAL(5,2))   #12345.12跟钱有关的用DECIMAL
    is_delete = Column(BOOLEAN)      
    create_time = Column(DateTime,onupdate=datetime.now(),default=datetime.now())
    content = Column(LONGTEXT)
    tag = Column(Enum(tagEnum))   #枚举类型,使用类
    tag2 = Column(Enum("python","c#","java"))  #枚举类型,直接显示

Base.metadata.drop_all()
Base.metadata.create_all()

查询过滤fiter,条件and_,or_,in_,模糊查找_聚合函数func.avg,group_by,having

# ---coding:utf-8----
# 文件名: create_orm.py
# @Time:2020/4/19 18:17
import enum
from datetime import datetime
from random import random, randint

from sqlalchemy import create_engine, Column, Integer, String, DECIMAL, BOOLEAN, DateTime, Enum, and_, or_, func
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

HOSTNAME = '120.24.*.*'
PORT = '3306'
DATABASE = 'school'
USERNAME = 'python'
PASSWORD = '*'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URI)
Base = declarative_base(engine)
session = sessionmaker(engine)()

class tagEnum(enum.Enum):
    China = "国内"
    Europe = "欧洲"
    America = "美国"
    Other = "其他"
class Article(Base):
    __tablename__ = "article"
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(100), name="title_a", nullable=True, unique=True)
    price = Column(DECIMAL(5, 2))  # 12345.12
    is_delete = Column(BOOLEAN)
    create_time = Column(DateTime, onupdate=datetime.now(), default=datetime.now())
    content = Column(LONGTEXT)
    tag = Column(Enum(tagEnum))  # 枚举类型
    tag2 = Column(Enum("python", "c#", "java"))

    def __repr__(self):
        return self.title

# Base.metadata.drop_all()
# Base.metadata.create_all()

# for x in range(101):
#     article = Article(title="title:%s" % x, price=randint(1, 100))
# session.add(article)
# session.commit()

# filter条件 (相当于sql语句中的条件)
# articles = session.query(Article.title,Article.price).all()# 查询所有记录的title和price字段
# articles = session.query(Article).filter(Article.title=="title:90").first()   # 等于
# articles = session.query(Article).filter(Article.price>90).all()   # 大于
# articles = session.query(Article).filter(Article.title.like('%le:9_')).all()  #模糊查找%_通配符
# articles = session.query(Article).filter(Article.title.in_(["title:6", "title:10"])).all()  # in
# articles = session.query(Article).filter(Article.title.in_(session.query(Article.title).filter(Article.price >= 95))).all()  # in+ 查询结果
# articles = session.query(Article).filter(~Article.title.in_(["title:6", "title:10"])).all()  # not in
# articles = session.query(Article).filter(Article.tag.is_(None)).all()  # is null
# articles = session.query(Article).filter(Article.price.isnot(None)).all()  # not null
# articles = session.query(Article).filter(and_(Article.title.like("title:9_"),Article.price<90)).all()    #and
# articles = session.query(Article).filter(or_(Article.title.like("title:9_"),Article.price>90)).all()    #or
# articles = session.query(Article).filter(or_(Article.title.like("title:9_"),Article.price>90)).all()    # 如果想要查看orm底层转换的sql语句,可以在filter方法后面不要再执行任何方法直接打印就可以看到了
# print(articles)

# 遍历并打印结果
# for a in articles:
#     print(a,a.price)


# 聚合函数 session.query(func.count(Article.id)).first()

# count = session.query(func.count(Article.id)).first()  #func.count  数量
# avg = session.query(func.avg(Article.price)).first()  #func.avg  平均数
# min = session.query(func.min(Article.price)).first()  #func.min 最小数
# max = session.query(func.max(Article.price)).first()  #func.max 最大数
# sum = session.query(func.sum(Article.price)).first()  #func.sum 和
#
# print(count,avg,min,max,sum)

# group_by,having的格式
articles = session.query(Article.price).filter(Article.price>50).group_by(Article.price).having(Article.price>70).all()
for a in articles:
    print(a)

表间关系

1对多

步骤:
1.建两个一对多的表,如user和article表,一个用户可以写多篇文章,user是"一",article是"多";建立外键和orm映射操作都在"多"表上.
2. article的uid与user的id建立外键约束.uid = Column(Integer, ForeignKey(“user.id”)),这是普通关系型数据库的范围,因此用的是表名
3. 在article上建立虚拟字段author,用于建立orm关系 author=relationship(“User”,backref=“articles”)
4. 输入数据:user表正常输入,article表的记录的uid由author输入:article1.author = user1
5. 正向查询(从article查user):article.author; 反向查询(从user查article):user.articles
(articles是在author中定义的backref值)

# ---coding:utf-8----
# 文件名: one_2_many.py
# @Time:2020/4/20 22:50
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref, sessionmaker

HOSTNAME = '120.24.*.*'
PORT = '3306'
DATABASE = 'school'
USERNAME = 'python'
PASSWORD = '*'        
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URI)

Base = declarative_base(engine)
session = sessionmaker(engine)()

class User(Base):    # 一对多中的"一,表名是user,有id和username两个字段"
    __tablename__ = "user"   # 表名
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(50), nullable=False)

    def __repr__(self):   # 对象显示值
        return "User(username:%s)" % self.username

class Article(Base):  # 一对多中的"多"表,表名是article,外键和orm关系设置均在此
    __tablename__ = "article"
    id = Column(Integer, primary_key=True, autoincrement=True)
    uid = Column(Integer, ForeignKey("user.id"))  # 1.先设外键,uid对应user表的id(user.id),因为是sql传统创建外键的方法,故使用表名
    title = Column(String(50), unique=True, nullable=False)
    content = Column(LONGTEXT)
    author = relationship('User', backref='articles')  #2.建立orm的关系,因此要使用类名User.author是虚拟的字段,用于正向查询,backref名称自设,用于反向查询.以article表为起点,从文章查询作者user表为正向;从作者user查询文章article为反向.

    def __repr__(self):
        return "Article(title:%s,content:%s)" % (self.title, self.content)

# 删除表/创建表
# Base.metadata.drop_all()        
# Base.metadata.create_all()
#增加记录(先增加1对多的1表--user表)
# user1 = User(username="张学友")
# user2 = User(username="刘德华")
# user3 = User(username="黎明")
# # session.add_all([user1, user2, user3])
# session.commit()
# 不直接输入uid,-
# # article1 = Article(title="吻别", content="前尘往事成云烟...") 
# 由orm自己映射
# # article1.author = user1
# # article2 = Article(title="真永远", content="哪一个人哪一份情...")
# # article2.author = user2
# # article3 = Article(title="今夜你会不会来", content="今夜你会不会来,你的爱还在不在...")
# # article3.author = user3
# article4 = Article(title="祝福", content="伤离别,离别虽然在眼前...")
# article4.author = user1
# # session.add_all([article1,article2,article3])
# session.add(article4)
# session.commit()

article = session.query(Article).filter_by(id=1).first()
print(article.author)

user = session.query(User).filter_by(id=1).first()
print(user.articles)

一对一

在sqlalchemy中,如果想要将两个模型映射成一对一的关系,那么应该在父模型中,指定引用的时候,要传递一个uselist=False这个参数进去。就是告诉父模型,以后引用这个从模型的时候,不再是一个列表了,而是一个对象了当然,也可以借助sqlalchemy.orm.backref来简化代码:

# ---coding:utf-8----
# 文件名: one2one.py
# @Time:2020/4/21 9:49
from sqlalchemy import create_engine, Column, Integer, String, BOOLEAN, ForeignKey
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref, Session, sessionmaker

HOSTNAME = '120.24.*.8'
PORT = '3306'
DATABASE = 'school'
USERNAME = 'python'
PASSWORD = '*'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URI)
Base = declarative_base(engine)
session = sessionmaker(engine)()
# 一对一操作步骤与一对多很像,将任一表当一,另一表当多即可.在建立orm关系时稍有不同,不仅仅是命名,还要使用uselist=False确立一对一关系(不是多对一关系):
user = relationship("User", backref=backref("extent", uselist=False))
class User(Base):  
    __tablename__ = "user_original"
    id = Column(Integer,primary_key=True,autoincrement=True)
    username = Column(String(20),nullable=False)
    password = Column(String(20),nullable=False)
    def __repr__(self):
        return self.username

class UserExtent(Base):
    __tablename__ = "user_extent"
    id = Column(Integer,primary_key=True,autoincrement=True)
    sex = Column(BOOLEAN)
    age = Column(Integer)
    nickname = Column(String(20))
    uid = Column(Integer,ForeignKey("user_original.id"))
    user = relationship("User", backref=backref("extent", uselist=False))  #此处backref的值稍有不同
    def __repr__(self):
        return self.nickname

# Base.metadata.drop_all()
# Base.metadata.create_all()

# u1 = User(username="宋江", password="sj")
# u2 = User(username="武松", password="ws")
# session.add_all([u1,u2])
# session.commit()
# # 删除user记录
# def del_data(name):
#     u_d = session.query(User).filter_by(username=name).first()
#     session.delete(u_d)
#     session.commit()
# # del_data("武松")
#
#
# u_e1 = UserExtent(sex=True,age=41,nickname="及时雨")
# u_e2 = UserExtent(sex=True,age=25,nickname="行者")
#
#
# u_e1.user = u1
#
# u_e2.user = u2
#
# session.add_all([u_e1,u_e2])
# session.commit()

# 验证
q1 = session.query(UserExtent).filter_by(id=1).first()
print(q1.user.id)

q2 = session.query(User).filter_by(id=10).first()
print(q2.extent)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值