一、数据库框架
数据库框架是数据库的抽象层,也称为对象关系映射(Object-Relational Mapper, ORM),它将高层的面向对象操作转换成低层的数据库指令,比起直接操作数据库引擎,ORM极大的提高了易用性。这种转换会带来一定的性能损耗,但ORM对生产效率的提升远远超过这一丁点儿性能降低。
Django中内置的SQLAlchemy ORM就是一个很好的数据库框架,它为多种关系型数据库引擎提供抽象层,比如MySQL, Postgres,SQLite,并且使用相同的面向对象接口。因此,使用SQLAlchemy ORM,不仅能极大的提高生产力,而且可以方便的在多种数据库之间迁移。
二、配置数据库
我们可以在项目文件夹的settins.py中配置数据库引擎。
Django默认使用sqlite:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3', # sqlite引擎
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
如果要要使用mysql, 需要进行如下配置:
1 编辑项目文件夹下的settings.py
:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # mysql引擎
'NAME': 'BookManagement',
# 数据库名称, 需要通过命令‘CREATE DATABASE BookManagement’在mysql命令窗口中提前创建
'USER': 'root', #你的数据库用户名
'PASSWORD': '***', #你的数据库密码
'HOST': '', #你的数据库主机,留空默认为localhost
'PORT': '3306', #你的数据库端口
}
}
2 编辑项目文件夹下的__init__.py
:
由于mysql在Django中默认驱动是MySQLdb, 而该驱动不适用于python3, 因此,我们需要更改驱动为PyMySQL
import pymysql
pymysql.install_as_MySQLdb()
3 显示SQL语句
前面我们说了ORM将高层的面向对象的操作,转换为低层的SQL语句,如果想在终端打印对应的SQL语句,可以在setting.py
中加上日志记录:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
三、模型
在ORM中,用模型(Model)表示数据库中一张表。模型的具体实现是一个Python类,类中的属性对应数据库表中的字段,这个类的实例化对象,对应表中的一条记录。
总结:类 –> 表; 类属性 –> 表字段; 类实例 –> 表记录
定义模型
定义模型就是定义一个python类,以创建一个图书管理系统为例,基本形式如下:
from django.db import models
class Publish(models.Model):
name = models.CharField(max_length=60)
addr = models.CharField(max_length=60)
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class Book(models.Model):
name = models.CharField(max_length=60)
price = models.DecimalField(max_digits=6, decimal_places=2)
publish = models.ForeignKey(Publish)
# 定义书与出版社的多对一关系
# 默认绑定到Publish表中的主键字段
authors = models.ManyToManyField(Author)
# 定义书与作者的多对多关系,ORM将自动创建多对多关系的第三张表
说明:
1. 定义完模型后,或者修改了模型后,要执行数据库迁移操作:
python manage.py makemigrations
python manage.py migrate
执行完命令后,查看数据库的表目录,可以看到上述表格成功创建:
2. 上述模型中都没有设置主键,在完成上迁移操作后,orm会自动创建主键。
3. orm会自动将Book表中的关联字段publish
, 在数据库中存为publish_id
, 所以不要画蛇添足自己命名为publish_id,否则你在数据库中看到的是publish_id_id
4. 外键引用的主表要么在子表前创建,要么使用字符串形式指定,否则子表找不到主表。
5. 如果我们实例化一个Book对象,book_obj, 那么通过book_obj.publish得到的是publish_id对应的那个Publish对象。这是ORM作的设定,原因很简单,如果通过book_obj.publish得到只是一个publish_id,对我们并没有多大用。
6. 虽然不是强制的,但是建议在每个类中定义__str__
方法(或__repr__
方法),这样当我们打印对象时,可以显示具有可读性的字符串信息,方便调试。
7. 只要在一张表中定义了多对多关系,orm会自动创建实现多对多关系的第三张表。当然,你也可以手动创建,如下:
class BookToAuthor(models.Model):
# 手动创建书与作者的多对多关系的第三张表
book = models.ForeignKey(Book)
author = models.ForeignKey(Author)
还是不建议手动创建,一是麻烦,而是后面我在执行删除记录的操作时,提示找不到第三关联表,可能是我表名命名问题,猜测应该将第三张表命名为Book_authors
的格式,这样才能和orm自动创建的第三张表同名,未验证。。。
字段类型
类型名 | Python类型 | 说明 |
---|---|---|
IntegerField | int | 普通整数,通常是32位,-2147483648 to 2147483647 |
SmallIntegerField | int | 小整数,一般是16位,-32768 to 32767 |
BigIntegerField | int/long | 64位的整数,-9223372036854775808 to 9223372036854775807 |
FloatField | float | 浮点数 |
DecimalField(max_digits=None, decimal_places=None | decimal.Decimal | 定点数,精度更高;要求指定位数和小数点精度。 |
CharField(max_length=None) | str | 字符串;要求指定最大长度 |
TextField | str | 变长字符串 |
BooleanField | bool | 布尔值 |
DateField | datetime.date | 日期,比如:2017-08-25 |
DateTimeField | datetime.datetime | 日期和时间 |
BinaryField | str | 二进制 |
更多类型请参考官网 field types
关系字段
字段 | 说明 |
---|---|
ForeignKey(othermodel) | 多对一关系,需要指定关系表 |
ManyToManyField(othermodel) | 多对多关系,需要指定关系表 |
OneToOneField(othermodel) | 一对一关系,需要指定关系表 |
字段选项
选项 | 说明 |
---|---|
primary_key | 如果设置primary_key=True, 这列就是表的主键;如果不指定,Django会自动添加一个AutoField字段来盛放主键,所以我们一般无需设定主键。 |
unique | 如果设置unique=True, 这列不允许出现重复的值 |
db_index | 如果设置db_index=True, 为这列创建索引,提升查询效率 |
null | 如果设置null=True, 这列允许使用空值;如果新增了字段,建议设置该选项,因为新增字段之前的记录没有该字段 |
default | 为这列定义默认值;如果新增了字段,建议设置该选项,因为新增字段之前的记录没有该字段 |
related_name | 在一对多关系多所在的表中定义反向引用;这样在一所在的表中反向查询多所在的表时,直接用这个字段就行了,可以替代下面要讲到的_set 反向查询 |
更多选项请参考官网 filed options
四、数据库的操作
下面通过python shell来演示数据库的操作。在终端切换到项目根目录下,输入命令python manage.py shell
进入shell操作环境:
增删改查
1 创建记录
方式一:实例化
>>> from app.models import Author #导入模型
>>> a = Author(name="张三") # 实例化
>>> a.save() # 插入记录
>>> print(a)
张三
方式二:create()
工厂函数
>>> Author.objects.create(name='李四')
<Author: 李四>
通过get_or_create()
创建记录,这种方法可以防止重复(速度稍慢,因为会先查询数据库),它返回一个元组,第一个是实例对象(记录),创建成功返回True,已存在则返回False,不执行创建。
>>> Author.objects.get_or_create(name='李四')
(<Author: 李四>, False)
2 查询记录
1 Author.objects.all()
查询所有
>>> Author.objects.all()
<QuerySet [<