首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

sqlachemy使用总结

2023-11-14 来源:华拓网

在flask中使用ORM  sqlchemy

1.新建modles.py.     如果已有数据表,https://www.devmashup.com/generating-flask-sqlalchemy-models-with-flask-sqlacodegen/  用flask-sqlacodegen来转成models.py

2.models.py中的模型类可以指定排序方式          __mapper_args__ = {"order_by": createtime.asc()}

也可以在查询条件中使用 order_by方法

.order_by(Order.updatetime.desc())

3.可以指定外键,  关联信息,  这样查一个表的时候,会把关联信息也返回   查用户的时候orders字段返回订单信息,    查订单表的时候,company字段返回用户信息,两个表一对多,多的用外键

https://blog.csdn.net/cswenrou/article/details/105256519

order表companyid = db.Column(db.Integer, ForeignKey("company.id"), info=‘公司ID‘)company = relationship("Company", back_populates="orders")company表
orders = relationship("Order", back_populates="company")

 

4.sqlachemy的数据查询使用modle模型orm,返回结果是模型对象,需要解析,使用flask_marshmallow;

新建schema.py,可以选择要返回的字段,返回字段的类型,嵌套数据

class OrderSchema(ma.SQLAlchemySchema): class Meta: model = Order fields = ( "id", "orderno", "title", "paytime", "assignordertime", "price", "company") price = fields.Str() company = fields.Nested(CompanySchema, attribute="company")

5.或者不使用relationship,直接在代码中进行关联查询

https://www.cnblogs.com/shenckicc/p/6797990.html

outerjoin方法是左连接filter方法是查询条件,要用模型.字段, 要使用 == >=等 filter_by 直接使用 字段=条件
with_entities查询指定的字段,返回的都是一个列表,列表内的元素是一个元组,不过不是 Python 内置的元组,是 sqlalchemy.util._collections.KeyedTuple。使用这个方法返回的数据转成python的dict dict(zip(i.keys(), i))
paginate方法,分页查询all方法查询全部first方法查询一条
     pagination = Order.query.outerjoin(OrderLawyer, OrderLawyer.orderid == Order.id).filter( Order.state == current_app.config[‘ORDER_STATE_CONFIRM‘] ).with_entities(Order.id, Order.orderno, Order.title, Order.paytime, Order.price, Order.costprice).order_by( Order.updatetime.desc()).paginate( page, per_page=current_app.config[‘PER_PAGE‘], error_out=False ) rows = pagination.items for i in rows: i = dict(zip(i.keys(), i))

 6. 添加一条数据后,马上要使用返回的id, 使用flush()马上入库

db.session.add(row)db.session.flush()
ret = Pm() #实例化模型对象ret.objectid = row.id #flush 之后可以使用row.id
db.session.add(ret) #添加记录
db.session.commit() #提交事务db.session.close() 

 

 

------------恢复内容结束------------

sqlachemy使用总结

标签:实例   comm   details   对象   nested   入库   page   shu   添加   

小编还为您整理了以下内容,可能对您也有帮助:

sqlalchemy做批量数据插入的时候要注意什么?有什么可以优化的

一、开始使用:

from sqlalchemy import create_engine

from sqlalchemy.orm import sessionmaker

DB_CONNECT_STRING = 'mysql+mysqldb://root:123@localhost/ooxx?charset=utf8'

engine = create_engine(DB_CONNECT_STRING, echo=True)

DB_Session = sessionmaker(bind=engine)

session = DB_Session()

这里的 DB_CONNECT_STRING 就是连接数据库的路径。“mysql+mysqldb”指定了使用 MySQL-Python 来连接,“root”和“123”分别是用户名和密码,“localhost”是数据库的域名,“ooxx”是使用的数据库名(可省略),“charset”指定了连接时使用的字符集(可省略)。

create_engine() 会返回一个数据库引擎,echo 参数为 True 时,会显示每条执行的 SQL 语句,生产环境下可关闭。

sessionmaker() 会生成一个数据库会话类。这个类的实例可以当成一个数据库连接,它同时还记录了一些查询的数据,并决定什么时候执行 SQL 语句。由于 SQLAlchemy 自己维护了一个数据库连接池(默认 5 个连接),因此初始化一个会话的开销并不大。对 Tornado 而言,可以在 BaseHandler 的 initialize() 里初始化:

class BaseHandler(tornado.web.RequestHandler):

def initialize(self):

self.session = models.DB_Session()

def on_finish(self):

self.session.close()

对其他 Web 服务器来说,可以使用 sqlalchemy.orm.scoped_session,它能保证每个线程获得的 session 对象都是唯一的。不过 Tornado 本身就是单线程的,如果使用了异步方式,就可能会出现问题,因此并没使用它。

拿到 session 后,就可以执行 SQL 了:

session.execute('create database abc')

print session.execute('show databases').fetchall()

session.execute('use abc')

# 建 user 表的过程略

print session.execute('select * from user where id = 1').first()

print session.execute('select * from user where id = :id', {'id': 1}).first()

不过这和直接使用 MySQL-Python 没啥区别;ORM 的方式,这也是采用 SQLAlchemy 的唯一原因。

于是来定义一个表:

from sqlalchemy import Column

from sqlalchemy.types import CHAR, Integer, String

from sqlalchemy.ext.declarative import declarative_base

BaseModel = declarative_base()

def init_db():

BaseModel.metadata.create_all(engine)

def drop_db():

BaseModel.metadata.drop_all(engine)

class User(BaseModel):

__tablename__ = 'user'

id = Column(Integer, primary_key=True)

name = Column(CHAR(30)) # or Column(String(30))

init_db()

declarative_base() 创建了一个 BaseModel 类,这个类的子类可以自动与一个表关联。

以 User 类为例,它的 __tablename__ 属性就是数据库中该表的名称,它有 id 和 name 这两个字段,分别为整型和 30 个定长字符。Column 还有一些其他的参数,我就不解释了。

最后,BaseModel.metadata.create_all(engine) 会找到 BaseModel 的所有子类,并在数据库中建立这些表;drop_all() 则是删除这些表。

接着就开始使用这个表吧:

from sqlalchemy import func, or_, not_

user = User(name='a')

session.add(user)

user = User(name='b')

session.add(user)

user = User(name='a')

session.add(user)

user = User()

session.add(user)

session.commit()

query = session.query(User)

print query # 显示SQL 语句

print query.statement # 同上

for user in query: # 遍历时查询

print user.name

print query.all() # 返回的是一个类似列表的对象

print query.first().name # 记录不存在时,first() 会返回 None

# print query.one().name # 不存在,或有多行记录时会抛出异常

print query.filter(User.id == 2).first().name

print query.get(2).name # 以主键获取,等效于上句

print query.filter('id = 2').first().name # 支持字符串

query2 = session.query(User.name)

print query2.all() # 每行是个元组

print query2.limit(1).all() # 最多返回 1 条记录

print query2.offset(1).all() # 从第 2 条记录开始返回

print query2.order_by(User.name).all()

print query2.order_by('name').all()

print query2.order_by(User.name.desc()).all()

print query2.order_by('name desc').all()

print session.query(User.id).order_by(User.name.desc(), User.id).all()

print query2.filter(User.id == 1).scalar() # 如果有记录,返回第一条记录的第一个元素

print session.query('id').select_from(User).filter('id = 1').scalar()

print query2.filter(User.id > 1, User.name != 'a').scalar() # and

query3 = query2.filter(User.id > 1) # 多次拼接的 filter 也是 and

query3 = query3.filter(User.name != 'a')

print query3.scalar()

print query2.filter(or_(User.id == 1, User.id == 2)).all() # or

print query2.filter(User.id.in_((1, 2))).all() # in

query4 = session.query(User.id)

print query4.filter(User.name == None).scalar()

print query4.filter('name is null').scalar()

print query4.filter(not_(User.name == None)).all() # not

print query4.filter(User.name != None).all()

print query4.count()

print session.query(func.count('*')).select_from(User).scalar()

print session.query(func.count('1')).select_from(User).scalar()

print session.query(func.count(User.id)).scalar()

print session.query(func.count('*')).filter(User.id > 0).scalar() # filter() 中包含 User,因此不需要指定表

print session.query(func.count('*')).filter(User.name == 'a').limit(1).scalar() == 1 # 可以用 limit() count() 的返回数

print session.query(func.sum(User.id)).scalar()

print session.query(func.now()).scalar() # func 后可以跟任意函数名,只要该数据库支持

print session.query(func.current_timestamp()).scalar()

print session.query(func.md5(User.name)).filter(User.id == 1).scalar()

query.filter(User.id == 1).update({User.name: 'c'})

user = query.get(1)

print user.name

user.name = 'd'

session.flush() # 写数据库,但并不提交

print query.get(1).name

session.delete(user)

session.flush()

print query.get(1)

session.rollback()

print query.get(1).name

query.filter(User.id == 1).delete()

session.commit()

print query.get(1)

二、进阶的知识。

1)如何批量插入大批数据?

可以使用非 ORM 的方式:

session.execute(

User.__table__.insert(),

[{'name': `randint(1, 100)`,'age': randint(1, 100)} for i in xrange(10000)]

)

session.commit()

如何批量插入大批数据?

可以使用非 ORM 的方式:

session.execute(

User.__table__.insert(),

[{'name': `randint(1, 100)`,'age': randint(1, 100)} for i in xrange(10000)]

)

session.commit()

上面批量插入了 10000 条记录,半秒内就执行完了;而 ORM 方式会花掉很长时间。

2)如何让执行的 SQL 语句增加前缀?

使用 query 对象的 prefix_with() 方法:

session.query(User.name).prefix_with('HIGH_PRIORITY').all()

session.execute(User.__table__.insert().prefix_with('IGNORE'), {'id': 1, 'name': '1'})

3)如何替换一个已有主键的记录?

使用 session.merge() 方法替代 session.add(),其实就是 SELECT + UPDATE:

user = User(id=1, name='ooxx')

session.merge(user)

session.commit()

或者使用 MySQL 的 INSERT … ON DUPLICATE KEY UPDATE,需要用到 @compiles 装饰器,有点难懂,自己看吧:《SQLAlchemy ON DUPLICATE KEY UPDATE》 和 sqlalchemy_mysql_ext。

4)如何使用无符号整数?

可以使用 MySQL 的方言:

from sqlalchemy.dialects.mysql import INTEGER

id = Column(INTEGER(unsigned=True), primary_key=True)

5)模型的属性名需要和表的字段名不一样怎么办?

开发时遇到过一个奇怪的需求,有个其他系统的表里包含了一个“from”字段,这在 Python 里是关键字,于是只能这样处理了:

from_ = Column('from', CHAR(10))

6)如何获取字段的长度?

Column 会生成一个很复杂的对象,想获取长度比较麻烦,这里以 User.name 为例:

User.name.property.columns[0].type.length

7)如何指定使用 InnoDB,以及使用 UTF-8 编码?

最简单的方式就是修改数据库的默认配置。如果非要在代码里指定的话,可以这样:

class User(BaseModel):

__table_args__ = {

'mysql_engine': 'InnoDB',

'mysql_charset': 'utf8'

}

MySQL 5.5 开始支持存储 4 字节的 UTF-8 编码的字符了,iOS 里自带的 emoji(如 🍎 字符)就属于这种。

如果是对表来设置的话,可以把上面代码中的 utf8 改成 utf8mb4,DB_CONNECT_STRING 里的 charset 也这样更改。

如果对库或字段来设置,则还是自己写 SQL 语句比较方便,具体细节可参考《How to support full Unicode in MySQL databases》。

不建议全用 utf8mb4 代替 utf8,因为前者更慢,索引会占用更多空间。

8)如何设置外键约束?

from random import randint

from sqlalchemy import ForeignKey

class User(BaseModel):

__tablename__ = 'user'

id = Column(Integer, primary_key=True)

age = Column(Integer)

class Friendship(BaseModel):

__tablename__ = 'friendship'

id = Column(Integer, primary_key=True)

user_id1 = Column(Integer, ForeignKey('user.id'))

user_id2 = Column(Integer, ForeignKey('user.id'))

for i in xrange(100):

session.add(User(age=randint(1, 100)))

session.flush() # 或 session.commit(),执行完后,user 对象的 id 属性才可以访问(因为 id 是自增的)

for i in xrange(100):

session.add(Friendship(user_id1=randint(1, 100), user_id2=randint(1, 100)))

session.commit()

session.query(User).filter(User.age < 50).delete()

执行这段代码时,应该会遇到一个错误:

sqlalchemy.exc.IntegrityError: (IntegrityError) (1451, 'Cannot delete or update a parent row: a foreign key constraint fails (`ooxx`.`friendship`, CONSTRAINT `friendship_ibfk_1` FOREIGN KEY (`user_id1`) REFERENCES `user` (`id`))') 'DELETE FROM user WHERE user.age < %s' (50,)原因是删除 user 表的数据,可能会导致 friendship 的外键不指向一个真实存在的记录。在默认情况下,MySQL 会拒绝这种操作,也就是 RESTRICT。InnoDB 还允许指定 ON DELETE 为 CASCADE 和 SET NULL,前者会删除 friendship 中无效的记录,后者会将这些记录的外键设为 NULL。

除了删除,还有可能更改主键,这也会导致 friendship 的外键失效。于是相应的就有 ON UPDATE 了。其中 CASCADE 变成了更新相应的外键,而不是删除。

而在 SQLAlchemy 中是这样处理的:

class Friendship(BaseModel):

__tablename__ = 'friendship'

id = Column(Integer, primary_key=True)

user_id1 = Column(Integer, ForeignKey('user.id', ondelete='CASCADE', onupdate='CASCADE'))

user_id2 = Column(Integer, ForeignKey('user.id', ondelete='CASCADE', onupdate='CASCADE'))

9)如何连接表?

from sqlalchemy import distinct

from sqlalchemy.orm import aliased

Friend = aliased(User, name='Friend')

print session.query(User.id).join(Friendship, User.id == Friendship.user_id1).all() # 所有有朋友的用户

print session.query(distinct(User.id)).join(Friendship, User.id == Friendship.user_id1).all() # 所有有朋友的用户(去掉重复的)

print session.query(User.id).join(Friendship, User.id == Friendship.user_id1).distinct().all() # 同上

print session.query(Friendship.user_id2).join(User, User.id == Friendship.user_id1).order_by(Friendship.user_id2).distinct().all() # 所有被别人当成朋友的用户

print session.query(Friendship.user_id2).select_from(User).join(Friendship, User.id == Friendship.user_id1).order_by(Friendship.user_id2).distinct().all() # 同上,join 的方向相反,但因为不是 STRAIGHT_JOIN,所以 MySQL 可以自己选择顺序

print session.query(User.id, Friendship.user_id2).join(Friendship, User.id == Friendship.user_id1).all() # 用户及其朋友

print session.query(User.id, Friendship.user_id2).join(Friendship, User.id == Friendship.user_id1).filter(User.id < 10).all() # id 小于 10 的用户及其朋友

print session.query(User.id, Friend.id).join(Friendship, User.id == Friendship.user_id1).join(Friend, Friend.id == Friendship.user_id2).all() # 两次 join,由于使用到相同的表,因此需要别名

print session.query(User.id, Friendship.user_id2).outerjoin(Friendship, User.id == Friendship.user_id1).all() # 用户及其朋友(无朋友则为 None,使用左连接)

在 Flask-SQLAlchemy 中联表查询

SQLAlchemy 是一个功能强大的 ORM 。 Flask-SQLAlchemy 是一个 Flask 插件,它让我们在 Flask 框架中使用 SQLAlchemy 变得更容易。

本篇介绍我在使用 Flask-SQLAlchemy 2.1 时进行联表查询的一些经验

这里有两个表,account 表保存帐号 ID 和昵称,bind 表保存 account 之间的绑定关系。

对应的 Model 如下:

先来看一个简单的例子:查询 gameuid 1000 账号下绑定的所有帐号。

看一看生成的 SQL 语句:

这里的联表查询使用的是 WHERE 语句。如果希望使用 JOIN 语句,可以这样写:

可以看出,现在生成的 SQL 语句已经使用 JOIN 语句了。但上面的语意有点奇怪,既然已经在 query 中使用了 Bind 和 Account,后面再 join 一次 Account 总觉得有点多余。那么 SQLAlchemy 如何选择 JOIN 的时候谁先谁后呢?看看这个错误就知道了:

这个错误显然说明,query 中参数的顺序很重要,第一个参数所代表的 table 就是 JOIN 时放在前面的那个 table。因此,此处 JOIN 的目标应该是 Account, 而不应该是 Bind 自身。

上面的例子已经解决了大多数需求了。我们再来看看分页。在 Flask-SQLAlchemy 中封装了一个 paginate 方法,可以方便地将查询记录进行分页:

报错的原因是 db.session.query 默认返回的是 orm.Query 对象,这个对象并不包含 paginate 方法。要解决这个问题,需要修改 Flask-SQLAlchemy 的源码。

找到 SQLAlchemy 对象的 __init__ 定义,在其中加入 session_options['query_cls'] = BaseQuery 即可:

在 Flask-SQLAlchemy 提供的 Model 对象中,可以使用 Model.query 这样的语法来直接得到一个查询对象,这是由于 Flask-SQLAlchemy 中存在一个 _QueryProperty 类,每次调用 Model.__get__ 时,会自动生成一个基于当前 session 的 query 对象:

使用 Model.query 得到的这个 query 对象可以直接进行 JOIN 操作,得到的结果是 Model 对象。这样就方便多了:

转换成 SQL 是这样的:

可以看出,这样的查询结果和使用 db.session.query 并没有什么不同。由于返回的是 Model 对象,使用上可能还更加方便了。

如何使用 Model.query.join 语法得到部分字段呢?这里可以使用 SQLAlchemy 提供的 with_entities 方法:

注意,列表中的项 (2, '玩家10001') 并不是标准的 Python tuple。你如果查看它的类型,会发现一个奇怪的名称: <class 'sqlalchemy.util._collections.result'> 。它是一个 AbstractKeyedTuple 对象,拥有一个 keys() 方法,这样可以很容易将其转换成 dict :

想了解 AbstractKeyedTuple ,可以看看这篇文档 New KeyedTuple implementation dramatically faster 。

除了筛选字段外,还可以用另一个方法获取多个 Model 的记录。那就是,返回两个 Model 的所有字段:

使用上面的语法直接返回 Account 和 Bind 对象,可以进行更加灵活的操作。

要联结超过 2 张以上的表,可以直接在 join 得到的结果之后链式调用 join 。也可以在 filter 的结果后面链式调用 join 。join 和 filter 返回的都是 query 对象,因此可以无限链式调用下去。

写完查询后,应该打印生成的 SQL 语句查看一下有没有性能问题。

sqlalchemy怎么多个数据库使用

一、开始使用:fromsqlalchemyimportcreate_enginefromsqlalchemy.ormimportsessionmakerDB_CONNECT_STRING='mysql+mysqldb://root:123@localhost/ooxx?charset=utf8'engine=create_engine(DB_CONNECT_STRING,echo=True)DB_Sess

sqlalchemy怎么多个数据库使用

一、开始使用:fromsqlalchemyimportcreate_enginefromsqlalchemy.ormimportsessionmakerDB_CONNECT_STRING='mysql+mysqldb://root:123@localhost/ooxx?charset=utf8'engine=create_engine(DB_CONNECT_STRING,echo=True)DB_Sess

sqlalchemy怎么修改表结构

SQLAlchemy有修改表结构的方法/工具

计算机VF:修改表结构的命令是MODIFY STRUCTURE 。

MODIFY STRUCTURE作用:显示表文件结构,并允许修改此表的结构。

VF常用命令

APPEND :在当前表的尾部(无论表中有无记录)追加记录(在当前表指当前正使用 的表)。 格式:APPEND [BLANK] 说明:在 APPEND 命令后面加上 BLANK 参数表示在当前表的尾部添加一条空 白记录。无 BLANK 参数时,表示在当前表的尾部添加一条记录并要求用户输入 相应的字段内容。

INSERT :在表文件中间插入一个新记录。 格式:INSERT [BEFORE] [BLANK] 说明:INSERT 在当前记录后插入一记录; INSERT BEFORE 在当前记录前插入一记录; INSERT BEFORE BLANK 在当前记录前插入一空记录。

BROWSE:主要用于打开浏览窗口,查阅表文件并同时进行修改。 格式:BROWSE。

USE :打开和关闭表文件。 格式:USE [<文件名>] USE 说明:前一个命令用来打开<文件名>指定的表文件,该表如有备注型字段,则 同时打开相应的备注文件(.fpt 文件);后一个命令关闭当前打开的表文件。

如何使用SQLAlchemy库写出防SQL注入的Raw SQL-WEB安全

1.永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或*长度;对单引号和
双"-"进行转换等。
2.永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
4.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装
6.sql注入的检测方法一般采取辅助软件或网站平台来检测,软件一般采用sql注入检测工具jsky,网站平台就有亿思网站安全平台检测工具。MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻击等。

如何使用SQLAlchemy库写出防SQL注入的Raw SQL-WEB安全

1.永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或*长度;对单引号和
双"-"进行转换等。
2.永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
4.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。
5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装
6.sql注入的检测方法一般采取辅助软件或网站平台来检测,软件一般采用sql注入检测工具jsky,网站平台就有亿思网站安全平台检测工具。MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻击等。

在python3下怎样用flask-sqlalchemy对mysql数据库操作

以 Debian/Ubuntu 为例(请确保有管理员权限):

1.MySQL

代码如下:

apt-get install mysql-server

apt-get install mysql-client

apt-get install libmysqlclient15-dev

2.python-mysqldb

代码如下:

apt-get install python-mysqldb

3.easy_install

代码如下:

wget http://peak.telecommunity.com/dist/ez_setup.py

python ez_setup.py

4.MySQL-Python

代码如下:

easy_install MySQL-Python

5.SQLAlchemy

代码如下:

easy_install SQLAlchemy

6、安装完成后使用下面代码测试连接

代码如下:

from sqlalchemy import create_engine

from sqlalchemy.orm import sessionmaker

DB_CONNECT_STRING = 'mysql+mysqldb://root:123@localhost/ooxx?charset=utf8'

engine = create_engine(DB_CONNECT_STRING, echo=True)

DB_Session = sessionmaker(bind=engine)

session = DB_Session()

7、数据操作(增删改查)

代码如下:

from sqlalchemy import func, or_, not_

user = User(name='a')

session.add(user)

user = User(name='b')

session.add(user)

user = User(name='a')

session.add(user)

user = User()

session.add(user)

session.commit()

query = session.query(User)

print query # 显示SQL 语句

print query.statement # 同上

for user in query: # 遍历时查询

print user.name

print query.all() # 返回的是一个类似列表的对象

print query.first().name # 记录不存在时,first() 会返回 None

# print query.one().name # 不存在,或有多行记录时会抛出异常

print query.filter(User.id == 2).first().name

print query.get(2).name # 以主键获取,等效于上句

print query.filter('id = 2').first().name # 支持字符串

query2 = session.query(User.name)

print query2.all() # 每行是个元组

print query2.limit(1).all() # 最多返回 1 条记录

print query2.offset(1).all() # 从第 2 条记录开始返回

print query2.order_by(User.name).all()

print query2.order_by('name').all()

print query2.order_by(User.name.desc()).all()

print query2.order_by('name desc').all()

print session.query(User.id).order_by(User.name.desc(), User.id).all()

print query2.filter(User.id == 1).scalar() # 如果有记录,返回第一条记录的第一个元素

print session.query('id').select_from(User).filter('id = 1').scalar()

print query2.filter(User.id > 1, User.name != 'a').scalar() # and

query3 = query2.filter(User.id > 1) # 多次拼接的 filter 也是 and

query3 = query3.filter(User.name != 'a')

print query3.scalar()

print query2.filter(or_(User.id == 1, User.id == 2)).all() # or

print query2.filter(User.id.in_((1, 2))).all() # in

query4 = session.query(User.id)

print query4.filter(User.name == None).scalar()

print query4.filter('name is null').scalar()

print query4.filter(not_(User.name == None)).all() # not

print query4.filter(User.name != None).all()

print query4.count()

print session.query(func.count('*')).select_from(User).scalar()

print session.query(func.count('1')).select_from(User).scalar()

print session.query(func.count(User.id)).scalar()

print session.query(func.count('*')).filter(User.id > 0).scalar() # filter() 中包含 User,因此不需要指定表

print session.query(func.count('*')).filter(User.name == 'a').limit(1).scalar() == 1 # 可以用 limit() count() 的返回数

print session.query(func.sum(User.id)).scalar()

print session.query(func.now()).scalar() # func 后可以跟任意函数名,只要该数据库支持

print session.query(func.current_timestamp()).scalar()

print session.query(func.md5(User.name)).filter(User.id == 1).scalar()

query.filter(User.id == 1).update({User.name: 'c'})

user = query.get(1)

print user.name

user.name = 'd'

session.flush() # 写数据库,但并不提交

print query.get(1).name

session.delete(user)

session.flush()

print query.get(1)

session.rollback()

print query.get(1).name

query.filter(User.id == 1).delete()

session.commit()

print query.get(1)

SQLAlchemy中的 backref具体用途

简单来说, relationship 函数是 sqlalchemy 对关系之间提供的一种便利的调用方式, backref 参数则对关系提供反向引用的声明。

我们只能像下面这样调用关系数据:

则我们可以直接在 User 对象中通过 addresses 属性获得指定用户的所有地址。

但是当我们有从 Address 对象获取所属用户的需求时, backref 参数就派上用场了。

backref 用于在关系另一端的类中快捷地创建一个指向当前类对象的属性, 而当需要对那个属性指定参数时使用 db.backref() 。

SQLAlchemy中的 backref具体用途

简单来说, relationship 函数是 sqlalchemy 对关系之间提供的一种便利的调用方式, backref 参数则对关系提供反向引用的声明。

我们只能像下面这样调用关系数据:

则我们可以直接在 User 对象中通过 addresses 属性获得指定用户的所有地址。

但是当我们有从 Address 对象获取所属用户的需求时, backref 参数就派上用场了。

backref 用于在关系另一端的类中快捷地创建一个指向当前类对象的属性, 而当需要对那个属性指定参数时使用 db.backref() 。

flask-sqlalchemy怎么用原生sql语句

为每一个工程创建一个独立的python运行环境是我们所需要的,python提供了virtualenv,可以为我们提供这个特殊的需求。
配置virtualenv环境
windows环境下运行cmd.exe,使用管理员权限运行。
pip install virtualenv

笔者使用的python版本是3.5.2,该版本中自动配置了pip应用,使用pip指令可以很方便的下载到你所需要的python拓展库。
安装成功后会出现successfully installed virtualenv字样。
PS:如果pip指令无法使用,请确认python环境下scripts是否包含在系统环境变量中的Path中。

使用控制台进入你需要配置该虚拟环境的目录,使用mkdir创建工程的文件夹,笔者创建的工程名为sqlalchemy_demo
mkdir sqlalchemy_demo

创建虚拟Python运行环境
virtualenv flask

出现如下字样,说明虚拟环境创建成功

flask-sqlalchemy怎么用原生sql语句

为每一个工程创建一个独立的python运行环境是我们所需要的,python提供了virtualenv,可以为我们提供这个特殊的需求。
配置virtualenv环境
windows环境下运行cmd.exe,使用管理员权限运行。
pip install virtualenv

笔者使用的python版本是3.5.2,该版本中自动配置了pip应用,使用pip指令可以很方便的下载到你所需要的python拓展库。
安装成功后会出现successfully installed virtualenv字样。
PS:如果pip指令无法使用,请确认python环境下scripts是否包含在系统环境变量中的Path中。

使用控制台进入你需要配置该虚拟环境的目录,使用mkdir创建工程的文件夹,笔者创建的工程名为sqlalchemy_demo
mkdir sqlalchemy_demo

创建虚拟Python运行环境
virtualenv flask

出现如下字样,说明虚拟环境创建成功

flask-SQLAlchemy 的 update 操作是怎么用的呢

flask-sqlalchemy使用MySQL的方式是:mysql://username:password@server/db结果我们照葫芦画瓢的来一下,发现压根不行,写好的网站一跟数据库沾边就报错。Python和MySQL是「两个国家的人」,他们互不相通,因而需要一个中间代理,让双方互通有无,跟翻译一样(这比喻不准确,但足够你明白意思就行)。翻译又有很多选择,不同的翻译各有特色。题主解决问题选择的翻译是「flask-mysqldb」,其背后的主子是「MySQL-python」。恩,说到这里你应该知道,「flask-xxx」这样的包都是对背后主子进行了适合Flask封装的插件,跟包子皮一样,里面的馅才是重点,「flask-mysqldb」的馅是「MySQL-python」。而我要推荐的是另一个翻译:PyMySQL,这玩意的好处是可以做异步(「MySQL-python」也可以,个人口味罢了),简而言之,网站访问量大了就需要考虑异步,现在别管这是啥子。这玩意的安装方式是:pip install PyMySQL之后,数据库连接由:mysql://username:password@server/db改为mysql+pymysql://username:password@server/db就可以了。

django orm 怎么对现有的表结构操作

pymysqlpymysql.install_as_MySQLdb()

并在settings.py文件修改DATABASES:

技术分享

 

技术分享
DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.mysql‘, ‘NAME‘: ‘xe‘, ‘USER‘: ‘a_user‘, #mysql的用户名 ‘PASSWORD‘: ‘a_password‘, #mysql的密码 ‘HOST‘: ‘‘, ‘PORT‘: ‘‘, }}
DATABASES

注意:NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建。

创建并生成数据库:

python manage.py makemigrationspython manage.py migrate

执行结果不报错就创建数据库成功了。

ORM(对象关系映射)

用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作。

优点:

1 ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句。快速开发,由此而来。

2 可以避免一些新手程序猿写sql语句带来的性能问题。

缺点:

1 性能有所牺牲,不过现在的各种ORM框架都在尝试各种方法,比如缓存,延迟加载登来减轻这个问题。效果很显著。

2  对于个别复杂查询,ORM仍然力不从心,为了解决这个问题,ORM一般也支持写raw sql。

 

下面用一个大家惯用的书籍/作者/出版商的数据库结构例子来学习Django ORM的语法。

表(模型)的创建:

实例:我们来假定下面这些概念,字段和关系

作者模型:一个作者有姓名。

作者详细模型:把作者的详情放到详情表,包含性别,email地址和出生日期,作者详情模型和作者模型之间是一对一的关系(one-to-one)(类似于每个人和他的身份证之间的关系),在大多数情况下我们没有必要将他们拆分成两张表,这里只是引出一对一的概念。

出版商模型:出版商有名称,地址,所在城市,省,国家和网站。

书籍模型:书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many),一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many),也被称作外键。

在我们自己建的app项目下的models.py文件

from django.db import modelsclass Publisher(models.Model): name = models.CharField(max_length=30, verbose_name="名称") address = models.CharField("地址", max_length=50) city = models.CharField(‘城市‘,max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Meta: verbose_name = ‘出版商‘ verbose_name_plural = verbose_name def __str__(self): return self.name class Author(models.Model): name = models.CharField(max_length=30) def __str__(self): return self.name class AuthorDetail(models.Model): sex = models.BooleanField(max_length=1, choices=((0, ‘男‘),(1, ‘女‘),)) email = models.EmailField() address = models.CharField(max_length=50) birthday = models.DateField() author = models.OneToOneField(Author) class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() price=models.DecimalField(max_digits=5,decimal_places=2,default=10) def __str__(self): return self.title

注意:记得在settings里的INSTALLED_APPS中加入我们自己创建的项目名,我的为‘app01’,然后再同步数据库。

分析代码:

1  每个数据模型都是django.db.models.Model的子类,它的父类Model包含了所有必要的和数据库交互的方法。并提供了一个简介漂亮的定义数据库字段的语法。

2  每个模型相当于单个数据库表(多对多关系例外,会多生成一张关系表),每个属性也是这个表中的字段。属性名就是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)。大家可以留意下其它的类型都和数据库里的什么字段对应。

3  模型之间的三种关系:一对一,一对多,多对多。

             一对一:实质就是在主外键(author_id就是foreign key)的关系基础上,给外键加了一个UNIQUE=True的属性;

            一对多:就是主外键关系;

            多对多:彼此一对多,自动创建第三张表

4  模型常用的字段类型以及参数

技术分享
# AutoField# 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.(参阅 _自动主键字段)# BooleanField# A true/false field. admin 用 checkbox 来表示此类字段.# CharField# 字符串字段, 用于较短的字符串.# # 如果要保存大量文本, 使用 TextField.# # admin 用一个 <input type="text"> 来表示此类字段 (单行输入).# # CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.# # CommaSeparatedIntegerField# 用于存放逗号分隔的整数值. 类似 CharField, 必须要有 maxlength 参数.# DateField# 一个日期字段. 共有下列额外的可选参数:# # Argument 描述# auto_now 当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.# auto_now_add 当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.# admin 用一个文本框 <input type="text"> 来表示该字段数据(附带一个 JavaScript 日历和一个"Today"快键.# # DateTimeField# 一个日期时间字段. 类似 DateField 支持同样的附加选项.# admin 用两上文本框 <input type="text"> 表示该字段顺序(附带JavaScript shortcuts). # # EmailField# 一个带有检查 Email 合法性的 CharField,不接受 maxlength 参数.# FileField# 一个文件上传字段.# # 要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime formatting, 该格式将被上载文件的 date/time 替换(so that uploaded files don‘t fill up the given directory).# # admin 用一个``<input type="file">``部件表示该字段保存的数据(一个文件上传部件) .# # 在一个 model 中使用 FileField 或 ImageField 需要以下步骤:# # 在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件. (出于性能考虑,这些文件并不保存到数据库.) 定义 MEDIA_URL 作为该目录的公共 URL. 要确保该目录对 WEB 服务器用户帐号是可写的.# 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django 使用 MEDIA_ROOT 的哪个子目录保存上传文件.# 你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). 出于习惯你一定很想使用 Django 提供的 get_<fieldname>_url 函数.举例来说,如果你的 ImageField 叫作 mug_shot, 你就可以在模板中以 {{ object.get_mug_shot_url }} 这样的方式得到图像的绝对路径.# FilePathField# 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.# # 参数 描述# path 必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目. Example: "/home/images".# match 可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名. 注意这个正则表达式只会应用到 base filename 而不是路径全名. Example: "foo.*.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.# recursive 可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.# 这三个参数可以同时使用.# # 我已经告诉过你 match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:# # FilePathField(path="/home/images", match="foo.*", recursive=True)# ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif# # FloatField# 一个浮点数. 必须 提供两个 参数:# # 参数 描述# max_digits 总位数(不包括小数点和符号)# decimal_places 小数位数# 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:# # models.FloatField(..., max_digits=5, decimal_places=2)# 要保存最大值一百万(小数点后保存10位)的话,你要这样定义:# # models.FloatField(..., max_digits=19, decimal_places=10)# admin 用一个文本框(<input type="text">)表示该字段保存的数据.# # ImageField# 类似 FileField, 不过要校验上传对象是否是一个合法图片.它有两个可选参数:height_field 和 width_field,如果提供这两个参数,则图片将按提供的高度和宽度规格保存.# # 该字段要求 Python Imaging Library.# # IntegerField# 用于保存一个整数.# # admin 用一个``<input type="text">``表示该字段保存的数据(一个单行编辑框)# # IPAddressField# 一个字符串形式的 IP 地址, (i.e. "24.124.1.30").# # admin 用一个``<input type="text">``表示该字段保存的数据(一个单行编辑框)# # NullBooleanField# 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项.# # admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据.# # PhoneNumberField# 一个带有合法美国风格电话号码校验的 CharField``(格式: ``XXX-XXX-XXXX).# PositiveIntegerField# 类似 IntegerField, 但取值范围为非负整数(这个字段应该是允许0值的....所以字段名字取得不太好,无符号整数就对了嘛).# PositiveSmallIntegerField# 类似 PositiveIntegerField, 取值范围较小(数据库相关)# SlugField# "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.它们通常用于URLs.# # 若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50. 在以前的 Django 版本,没有任何办法改变 50 这个长度.# # 这暗示了 db_index=True.# # 它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-populate the slug, via JavaScript, in the object‘s admin form:# # models.SlugField(prepopulate_from=("pre_name", "name"))# prepopulate_from 不接受 DateTimeFields.# # admin 用一个``<input type="text">``表示 SlugField 字段数据(一个单行编辑框) # # SmallIntegerField# 类似 IntegerField, 不过只允许某个取值范围内的整数.(依赖数据库)# # TextField# 一个容量很大的文本字段.# # admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).# # TimeField# A time. Accepts the same auto-population options as DateField 和 DateTimeField.# # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(附加一些JavaScript shortcuts).# # URLField# 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在(即URL是否被有效装入且没有返回404响应).# # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)# # USStateField# 一个两字母的美国州名缩写.# # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)# # XMLField# 一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema 的文件系统路径.
模型常用的字段类型以及参数

 

表的操作(增删改查):

  1  增(create  save)

技术分享

技术分享
>>> from app01.models import *>>> Author.objects.create(name=‘Alvin‘)<Author: Alvin>>>> AuthorDetail.objects.create(sex=False,email=‘916852314@qq.com‘,address=‘bejing‘,birthday=‘1995-3-16‘,author_id=1)<AuthorDetail: AuthorDetail object>>>> pub=Publisher()>>> pub.name=‘河大出版社‘>>> pub.address=‘保定‘>>> pub.city=‘保定‘>>> pub.state_province=‘河北‘>>> pub.country=‘China‘>>> pub.website=‘http://www.beida.com‘>>> pub.save()
View Code

注意:如果每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分:

技术分享
LOGGING = {# ‘version‘: 1,# ‘disable_existing_loggers‘: False,# ‘handlers‘: {# ‘console‘:{# ‘level‘:‘DEBUG‘,# ‘class‘:‘logging.StreamHandler‘,# },# },# ‘loggers‘: {# ‘django.db.backends‘: {# ‘handlers‘: [‘console‘],# ‘propagate‘: True,# ‘level‘:‘DEBUG‘,# },# }# }
View Code

那么如何创建存在一对多或多对多关系的一本书的信息呢?

技术分享

技术分享
>>> Book.objects.create(title=‘php‘,publisher=pub,publication_date=‘2017-7-7‘)<Book: php>>>> author1=Author.objects.get(id=1)>>> author2=Author.objects.get(name=‘alvin‘)>>> book=Book.objects.get(id=1)>>> book.authors.add(author1,author1)>>> book.authors.add(author1,author2)
View Code

2 改:

update和save方法

 

django之数据库orm

标签:self   file   app   text   一对一   子目录   美国   基础   开发   

django orm 怎么对现有的表结构操作

pymysqlpymysql.install_as_MySQLdb()

并在settings.py文件修改DATABASES:

技术分享

 

技术分享
DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.mysql‘, ‘NAME‘: ‘xe‘, ‘USER‘: ‘a_user‘, #mysql的用户名 ‘PASSWORD‘: ‘a_password‘, #mysql的密码 ‘HOST‘: ‘‘, ‘PORT‘: ‘‘, }}
DATABASES

注意:NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建。

创建并生成数据库:

python manage.py makemigrationspython manage.py migrate

执行结果不报错就创建数据库成功了。

ORM(对象关系映射)

用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作。

优点:

1 ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句。快速开发,由此而来。

2 可以避免一些新手程序猿写sql语句带来的性能问题。

缺点:

1 性能有所牺牲,不过现在的各种ORM框架都在尝试各种方法,比如缓存,延迟加载登来减轻这个问题。效果很显著。

2  对于个别复杂查询,ORM仍然力不从心,为了解决这个问题,ORM一般也支持写raw sql。

 

下面用一个大家惯用的书籍/作者/出版商的数据库结构例子来学习Django ORM的语法。

表(模型)的创建:

实例:我们来假定下面这些概念,字段和关系

作者模型:一个作者有姓名。

作者详细模型:把作者的详情放到详情表,包含性别,email地址和出生日期,作者详情模型和作者模型之间是一对一的关系(one-to-one)(类似于每个人和他的身份证之间的关系),在大多数情况下我们没有必要将他们拆分成两张表,这里只是引出一对一的概念。

出版商模型:出版商有名称,地址,所在城市,省,国家和网站。

书籍模型:书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many),一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many),也被称作外键。

在我们自己建的app项目下的models.py文件

from django.db import modelsclass Publisher(models.Model): name = models.CharField(max_length=30, verbose_name="名称") address = models.CharField("地址", max_length=50) city = models.CharField(‘城市‘,max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Meta: verbose_name = ‘出版商‘ verbose_name_plural = verbose_name def __str__(self): return self.name class Author(models.Model): name = models.CharField(max_length=30) def __str__(self): return self.name class AuthorDetail(models.Model): sex = models.BooleanField(max_length=1, choices=((0, ‘男‘),(1, ‘女‘),)) email = models.EmailField() address = models.CharField(max_length=50) birthday = models.DateField() author = models.OneToOneField(Author) class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() price=models.DecimalField(max_digits=5,decimal_places=2,default=10) def __str__(self): return self.title

注意:记得在settings里的INSTALLED_APPS中加入我们自己创建的项目名,我的为‘app01’,然后再同步数据库。

分析代码:

1  每个数据模型都是django.db.models.Model的子类,它的父类Model包含了所有必要的和数据库交互的方法。并提供了一个简介漂亮的定义数据库字段的语法。

2  每个模型相当于单个数据库表(多对多关系例外,会多生成一张关系表),每个属性也是这个表中的字段。属性名就是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)。大家可以留意下其它的类型都和数据库里的什么字段对应。

3  模型之间的三种关系:一对一,一对多,多对多。

             一对一:实质就是在主外键(author_id就是foreign key)的关系基础上,给外键加了一个UNIQUE=True的属性;

            一对多:就是主外键关系;

            多对多:彼此一对多,自动创建第三张表

4  模型常用的字段类型以及参数

技术分享
# AutoField# 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.(参阅 _自动主键字段)# BooleanField# A true/false field. admin 用 checkbox 来表示此类字段.# CharField# 字符串字段, 用于较短的字符串.# # 如果要保存大量文本, 使用 TextField.# # admin 用一个 <input type="text"> 来表示此类字段 (单行输入).# # CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.# # CommaSeparatedIntegerField# 用于存放逗号分隔的整数值. 类似 CharField, 必须要有 maxlength 参数.# DateField# 一个日期字段. 共有下列额外的可选参数:# # Argument 描述# auto_now 当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.# auto_now_add 当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.# admin 用一个文本框 <input type="text"> 来表示该字段数据(附带一个 JavaScript 日历和一个"Today"快键.# # DateTimeField# 一个日期时间字段. 类似 DateField 支持同样的附加选项.# admin 用两上文本框 <input type="text"> 表示该字段顺序(附带JavaScript shortcuts). # # EmailField# 一个带有检查 Email 合法性的 CharField,不接受 maxlength 参数.# FileField# 一个文件上传字段.# # 要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime formatting, 该格式将被上载文件的 date/time 替换(so that uploaded files don‘t fill up the given directory).# # admin 用一个``<input type="file">``部件表示该字段保存的数据(一个文件上传部件) .# # 在一个 model 中使用 FileField 或 ImageField 需要以下步骤:# # 在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件. (出于性能考虑,这些文件并不保存到数据库.) 定义 MEDIA_URL 作为该目录的公共 URL. 要确保该目录对 WEB 服务器用户帐号是可写的.# 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django 使用 MEDIA_ROOT 的哪个子目录保存上传文件.# 你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). 出于习惯你一定很想使用 Django 提供的 get_<fieldname>_url 函数.举例来说,如果你的 ImageField 叫作 mug_shot, 你就可以在模板中以 {{ object.get_mug_shot_url }} 这样的方式得到图像的绝对路径.# FilePathField# 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.# # 参数 描述# path 必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目. Example: "/home/images".# match 可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名. 注意这个正则表达式只会应用到 base filename 而不是路径全名. Example: "foo.*.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.# recursive 可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.# 这三个参数可以同时使用.# # 我已经告诉过你 match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:# # FilePathField(path="/home/images", match="foo.*", recursive=True)# ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif# # FloatField# 一个浮点数. 必须 提供两个 参数:# # 参数 描述# max_digits 总位数(不包括小数点和符号)# decimal_places 小数位数# 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:# # models.FloatField(..., max_digits=5, decimal_places=2)# 要保存最大值一百万(小数点后保存10位)的话,你要这样定义:# # models.FloatField(..., max_digits=19, decimal_places=10)# admin 用一个文本框(<input type="text">)表示该字段保存的数据.# # ImageField# 类似 FileField, 不过要校验上传对象是否是一个合法图片.它有两个可选参数:height_field 和 width_field,如果提供这两个参数,则图片将按提供的高度和宽度规格保存.# # 该字段要求 Python Imaging Library.# # IntegerField# 用于保存一个整数.# # admin 用一个``<input type="text">``表示该字段保存的数据(一个单行编辑框)# # IPAddressField# 一个字符串形式的 IP 地址, (i.e. "24.124.1.30").# # admin 用一个``<input type="text">``表示该字段保存的数据(一个单行编辑框)# # NullBooleanField# 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项.# # admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据.# # PhoneNumberField# 一个带有合法美国风格电话号码校验的 CharField``(格式: ``XXX-XXX-XXXX).# PositiveIntegerField# 类似 IntegerField, 但取值范围为非负整数(这个字段应该是允许0值的....所以字段名字取得不太好,无符号整数就对了嘛).# PositiveSmallIntegerField# 类似 PositiveIntegerField, 取值范围较小(数据库相关)# SlugField# "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.它们通常用于URLs.# # 若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50. 在以前的 Django 版本,没有任何办法改变 50 这个长度.# # 这暗示了 db_index=True.# # 它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-populate the slug, via JavaScript, in the object‘s admin form:# # models.SlugField(prepopulate_from=("pre_name", "name"))# prepopulate_from 不接受 DateTimeFields.# # admin 用一个``<input type="text">``表示 SlugField 字段数据(一个单行编辑框) # # SmallIntegerField# 类似 IntegerField, 不过只允许某个取值范围内的整数.(依赖数据库)# # TextField# 一个容量很大的文本字段.# # admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).# # TimeField# A time. Accepts the same auto-population options as DateField 和 DateTimeField.# # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(附加一些JavaScript shortcuts).# # URLField# 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在(即URL是否被有效装入且没有返回404响应).# # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)# # USStateField# 一个两字母的美国州名缩写.# # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)# # XMLField# 一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema 的文件系统路径.
模型常用的字段类型以及参数

 

表的操作(增删改查):

  1  增(create  save)

技术分享

技术分享
>>> from app01.models import *>>> Author.objects.create(name=‘Alvin‘)<Author: Alvin>>>> AuthorDetail.objects.create(sex=False,email=‘916852314@qq.com‘,address=‘bejing‘,birthday=‘1995-3-16‘,author_id=1)<AuthorDetail: AuthorDetail object>>>> pub=Publisher()>>> pub.name=‘河大出版社‘>>> pub.address=‘保定‘>>> pub.city=‘保定‘>>> pub.state_province=‘河北‘>>> pub.country=‘China‘>>> pub.website=‘http://www.beida.com‘>>> pub.save()
View Code

注意:如果每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分:

技术分享
LOGGING = {# ‘version‘: 1,# ‘disable_existing_loggers‘: False,# ‘handlers‘: {# ‘console‘:{# ‘level‘:‘DEBUG‘,# ‘class‘:‘logging.StreamHandler‘,# },# },# ‘loggers‘: {# ‘django.db.backends‘: {# ‘handlers‘: [‘console‘],# ‘propagate‘: True,# ‘level‘:‘DEBUG‘,# },# }# }
View Code

那么如何创建存在一对多或多对多关系的一本书的信息呢?

技术分享

技术分享
>>> Book.objects.create(title=‘php‘,publisher=pub,publication_date=‘2017-7-7‘)<Book: php>>>> author1=Author.objects.get(id=1)>>> author2=Author.objects.get(name=‘alvin‘)>>> book=Book.objects.get(id=1)>>> book.authors.add(author1,author1)>>> book.authors.add(author1,author2)
View Code

2 改:

update和save方法

 

django之数据库orm

标签:self   file   app   text   一对一   子目录   美国   基础   开发   

显示全文