数据库
-
操作数据库
-
配置连接数据库
在settings.py中配置
DATABASES = { 'default': { # 数据库引擎(是mysql还是oracle等) 'ENGINE': 'django.db.backends.mysql', # 数据库的名字 'NAME': 'dfz', # 连接mysql数据库的用户名 'USER': 'root', # 连接mysql数据库的密码 'PASSWORD': 'root', # mysql数据库的主机地址 'HOST': '127.0.0.1', # mysql数据库的端口号 'PORT': '3306', } }
-
操作方式
-
使用原生的sql语句来操作,python db api的接口来操作。
# 使用django封装好的connection对象, 会自动读取settings.py中数据库的配置信息 from django.db import connection # 获取游标对象 cursor = connection.cursor() # 拿到游标对象后执行sql语句 cursor.execute("select * from book") # 获取所有的数据 rows = cursor.fetchall() # 遍历查询到的数据 for row in rows: print(row)
常用对象接口
-
description
如果 cursor 执行了查询的 sql 代码。 那么读取 cursor.description 属性的
时候, 将返回一个列表, 这个列表中装的是元组, 元组中装的分别
是 (name,type_code,display_size,internal_size,precision,scale,null_ok) , 其中 name 代表的是查找出来的数据的字段名称, 其他参数暂时用处不大。 -
rowcount
代表的是在执行了sql语句后受影响的行数
-
close
关闭游标。
-
execute(sql[,parameters])
执行某个 sql 语句。 如果在执行 sql 语句的时候还需要传递
参数, 那么可以传给 parameters 参数。cursor.execute("select * from article where id=%s",(1,))
-
fetchone
在执行了查询操作以后,获取第一条数据。
-
fetchmany(size)
在执行了查询操作以后,获取多条数据。具体是多少条要看传的size参数。
-
fetchall
获取所有满足sql语句的数据。
-
-
使用ORM模型来操作
对象关系映射,通过ORM,可以通过类的方式去操作数据库,而不用再写原生的SQL语句。通过把表映射成类,把行作为实例,把字段作为属性,ORM在执行对象操作的时候最终还是会把对应的操作转换为数据库原生语句。
-
创建ORM模型
一般存放在app的model.py文件中,每个app都可以有自己的模型。
- 在settings.py中,配置好DATABASES,做好数据库相关的配置。
- 在app中的models.py中定义好模型,这个模型必须继承django.db.models。
- 将这个app添加到settings.py的INSTALLED_APP中。
- 在命令行终端执行python manage.py makemigrations来生成迁移脚本文件。
- 执行python manage.py migrate 来将迁移脚本文件映射到数据库中。
-
-
-
-
模型常用属性
-
常用字段
-
AutoField
映射到数据库中是int类型,可以有自定增长的特性。一般不需要使用这个类型,如果不指定主键,那么模型会自动的生成一个叫做id的自动增长的主键。如果你想指定一个其他名字的并且具有自动增长的主键,使用AutoField。
-
BigAutoField
64位的整形,类似于AutoField。
-
BooleanField
在模型层面接收的是True/False。在数据库层面是tinyint类型。默认为None。
-
CharField
在数据库层面是varchar类型。在Python层面就是普通的字符串。这个类型在使用的时候必须要指定最大的长度,也即必须要传递max_length这个关键字参数进去。
-
DateField
日期类型。在Python中是datetime.date类型,可以记录年月日。在映射到数据库中也是date类型。
-
auto_now
在每次这个数据保存的时候,都使用当前的时间。true/false
-
auto_now_add
在每次数据第一次被添加进去的时候,都使用当前时间。true/false
-
-
DateTimeField
日期时间类型。类似于DateField。存储日期和时间。映射到数据库中是datetime类型。同样有auto_now 和 auto_now_add。
-
TimeField
时间类型。在数据库中是time类型。
-
EmailField
类似CharField。
-
FileField
用来存储文件的。
-
ImageField
用来存储图片文件的。
-
FloatField
浮点类型。映射到数据库中是float类型。
-
IntegerField
整形。
-
BigIntegerField
大整形。
-
PositiveIntegerField
正整形。
-
SmallIntegerField
小整形。
-
PositiveSmallIntegerField
正小整形。
-
TextField
大量的文本类型。
-
UUIDField
只能存储uuid格式的字符串。uuid是一个32位的全球唯一的字符串,一般用来作为主键。
-
URLField
类似于CharField,只不过只能用来存储url格式的字符串。
-
-
常用参数
-
null
如果设置为 True ,Django 将会在映射表的时候指定是否为空。 默认是为 False 。 在使用字符串相关的 Field ( CharField/TextField) 的时候, 官方推荐尽量不要使用这个参数, 也就是保持默认值 False 。 因为 Django 在处理字符串相关的 Field 的时候, 即使这个 Field 的 null=False , 如果你没有给这个 Field 传递任何值, 那么 Django 也会使用一个空的字符串 “” 来作为默认值存储进去。 因此如果再使用 null=True ,Django 会产生两种空值的情形( NULL或者空字符串) 。 如果想要在表单验证的时候允许这个字符串为空, 那么建议使用 blank=True 。 如果你的 Field 是 BooleanField , 那么对应的可空的字段则为 NullBooleanField 。
-
blank
标识这个字段在表单验证的时候是否可以为空。null是一个纯数据库级别的。blank是表单验证级别的。
-
db_column
这个字段来设置在数据库中的名字,如果没有设置这个参数,那么将会使用模型中属性的名字。
-
default
默认值。可以为一共值,或者是一个函数,但是不支持lambda表达式。并且不支持列表/字典/集合等可变的数据结构。
-
primary_key
是否为主键,默认为False。
-
unique
在表中这个字段的值是否唯一。一般是设置手机号/邮箱等。
-
模型中Meta配置
class Book(model.Model): pass class Meta: db_table = 'book_model'
-
db_table
这个模型映射到数据库中的表明。如果没有指定这个参数,那么在映射的时候将会使用模型明来作为默认的表明
-
ordering
设置在提取数据的排序方式。
-
verbose_name
设置在admin中显示的名字
-
-
-
外键和表关系
-
外键
类定义为
class ForeignKey(to, on_delete, **options)
第一个参数是引用的哪个模型,第二个参数是在使用外键引用的模型数据被删除了,这个字段该如何处理。class User(models.Model): username = models.CharField(max_length=20) password = models.CharField(max_length=20) class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() author = models.ForeignKey("User",on_delete=models.CASCADE)
修改字段内容
article = Article(title='abc',content='123') author = User(username='张三',password='111111') article.author = author article.save() # 修改article.author上的值 article.author.username = '李四' article.save() # 当外键引用自身的时候,to参数可以为'self'或者这个模型的名字。
外键删除操作
如果一个模型使用了外键,那么在对方那个模型被删除掉以后,该进行怎么样的操作,可以通过on_delete来指定。
-
CASCADE
级联操作。如果外键对应的那条数据被删除了,那么这条数据也会被删除。
-
PROTECT
受保护。即只要这条数据引用了外键的那条数据,那么就不能删除外键的那条数据。
-
SET_NULL
设置为空。如果外键的那条数据被删除了,那么在本条数据上就将这个字段设置为空。
-
SET_DEFAULT
设置默认值。如果外键那条数据被删除了,那么在本条数据上就将这个字段设置为默认值。
-
SET()
如果外键的那条数据被删除 ,那么将会获取SET函数中的值来作为这个外键的值。SET函数可以接收一个可以调用的对象,如果是可以调用的对象,那么会将这个对象调用后的结果作为值返回回去。
-
DO_NOTHING
不采取任何行为。
-
-
表关系
-
一对多
class User(models.Model): username = models.CharField(max_length=20) password = models.CharField(max_length=100) class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() author = models.ForeignKey("User",on_delete=models.CASCADE) article = Article(title='abc',content='123') author = User(username='zhiliao',password='111111') # 要先保存到数据库中 author.save() article.author = author article.save() # 通过Article_set user = User.objects.first() # 获取第一个用户写的所有文章 articles = user.article_set.all for article in articles: print(article)
-
一对一
class User(models.Model): username = models.CharField(max_length=20) password = models.CharField(max_length=100) class UserExtension(models.Model): birthday = models.DateTimeField(null=True) school = models.CharField(blank=True,max_length=50) user = models.OneToOneField("User", on_delete=models.CASCADE)
-
多对多
class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() tags = models.ManyToManyField("Tag",related_name="articles") class Tag(models.Model): name = models.CharField(max_length=50)
-
-
模型一般操作
在ORM框架中,所有模型相关的操作,比如添加/删除等。
-
添加一个模型到数据库中
首先需要创建一个模型,创建模型的方式很简单,就跟创建普通的Python对象是一模一样。
创建完成以后,调用模型的save方法,这样Django会自动的将这个模型转换成sql语句,然后存储到数据库中。
class Book(models.Model): name = models.CharField(max_length=20,null=False) desc = models.CharField(max_length=100,name='description',db_column="description1") book = Book(name='三国演义',desc='三国英雄!') book.save()
-
查找数据
查找数据都是通过模型下的objects对象来实现的。
-
查找所有数据
books = Book.objects.all()
-
数据过滤
在查找数据的时候,有时候需要对一些数据进行过滤。
books = Book.objects.filter(name='三国演义') # 多个条件 books = Book.objects.filter(name='三国演义',desc='test')
-
获取单个对象
book = Book.objects.get(name='三国演义')
如果没有找到满足条件的数据,就会抛出一个异常。
-
数据排序
books = Book.objects.order_by("pub_date")
正序books = Book.objects.order_by("-pub_date")
倒序 -
修改数据
from datetime import datetime book = Book.objects.get(name='三国演义') book.pub_date = datetime.now() book.save()
-
删除数据
book = Book.objects.get(name='三国演义') book.delete()
-
-
模型查询操作
-
查询条件
-
exact
使用精确的
=
进行查找。article = Article.objects.get(id__exact=14)
-
iexact
使用
like
进行查找。article = Article.objects.filter(title__iexact='hello world')
-
contains
大小写敏感,判断某个字段是否包含了某个数据。
articles = Article.objects.filter(title__contains='hello')
-
icontains
大小写不敏感的匹配查询。
articles = Article.objects.filter(title_icontains='hello')
-
in
提取那些给定的field的值是否在给定的容器中。容器可以为list,tuple或者任何一个可以迭代的对象。
articles = Article.objects.filter(id__in=[1,2,3])
也可以传递一个QuerySet对象进去。
inner_qs = Article.objects.filter(title__contains='hello') categories = Category.objects.filter(article__in=inner_qs)
-
gt
某个field的值大于给定的值。
articles = Article.objects.filter(id__gt=4)
-
gte
大于等于
-
lt
小于
-
lte
小于等于
-
startwith
判断某个字段的值是否是以某个值开始的,大小写敏感。
articles = Article.objects.filter(title__startswith='hello')
-
istartswith
类似 startwith 但是大小写不敏感。
-
endswith
判断某个字段的值是否以某个值结束,大小写敏感。
-
iendswith
与endswith类似,只不过大小写不敏感。
-
range
判断某个field的值是否在给定的区间中。
from django.utils.timezone import make_aware from datetime import datetime start_date = make_aware(datetime(year=2018,month=1,day=1)) end_date = make_aware(datetime(year=2018,month=3,day=29,hour=16)) articles = Article.objects.filter(pub_date__range=(start_date,end_date))
-
date
针对某个date或者datetime类似的字段。可以指定date的范围,并且这个时间过滤,还可以使用链式调用。
articles = Article.objects.filter(pub_date__date=date(2018,3,29))
-
year
按照年份查询。
-
month
按照月份查询。
-
day
按照日期查询
-
week_day
按照星期来查询。1为星期天。
-
time
按照时间查询
articles = Article.objects.filter(pub_date__time=datetime.time(12,12,12));
-
isnull
根据值是否为空进行查找。
articles = Article.objects.filter(pub_date__isnull=False)
-
regex iregex
大小写敏感和大小写不敏感的正则表达式。
-
-
聚合函数
-
Avg
求平均值。
Book.objects.aggregate(Avg('price'))
Book.objects.aggregate(my_avg=Avg('price'))
-
Count
获取指定的对象的个数。
esult = Author.objects.aggregate(count=Count('email',distinct=True))
其中,distinct 为指定是否去掉重复值。
-
Max Min
获取指定对象的最大值和最小值。
-
Sum
求和。
-
-
F表达式
是用来优化ORM操作数据库的。
-
Q表达式
实现通过多个查询条件进行查询。
books = Book.objects.filter(Q(price__lte=10) | Q(rating__lte=9))
-
QuerySet API
-
可以返回新的QuerySet的方法
-
filter
-
exclude 排除满足条件的数据
-
annotate 给QuerySet中的每个对象都添加一个使用查询的表达式的新字段。
Article.objects.annotate(author_name=F("author_name"))
-
order_by
-
values 用来指定在提取数据出来,需要提取哪些字段。
-
values_list 类似于values。返回的不是字典,是元组。
-
all 获取这个ORM模型的QuerySet对象。
-
select_related 在提取某个模型的数据的同时,也提前将相关联的数据提取出来,从而减少对数据库查询的次数。但是只能用在一对多,一对一的情况。
article = Article.objects.select_related("author").get(pk=2)
-
prefetch_related 这个方法和select_related非常类似,但是解决了多对一和多对多的关系的查询问题。
-
defer 会过滤掉一些字段,返回的是一个模型。
-
only 只提取指定字段。
-
get 获取满足条件的数据。
-
create 创建一条数据,并且保存到数据库中。相当于先用指定的模型创建一个对象,然后再调用这个对象的save方法。
-
get_or_create 根据某个条件进行查找,如果找到了就返回这条数据,如果没有查找到,就创建一个。
-
bulk_create 一次性创建多个数据。
Tag.objects.bulk_create([ Tag(name='111'), Tag(name='222'), ])
-
count 获取提取的数据的个数。
-
first和last 返回QuerySet中的第一条和最后一条数据。
-
aggregate 使用聚合函数。
-
exists 判断某个条件的数据是否存在。
if Article.objects.filter(title__contains='hello').exists():
-
distinct 去除掉那些重复的数据。
-
update 执行更新操作。
Article.objects.filter(category__isnull=True).update(category_id=3)
-
delete 删除所有满足条件的数据。
-
切片操作。
-
-
-
-
-
ORM 模型迁移
-
迁移命令
-
makemigrations
将模型生成迁移脚本。后面加一个或者多个app,那么就会针对这几个app生成迁移脚本。
-
migrate
将新生成的迁移映射到数据中。
-
showmigrations
查看某个app下的迁移文件
-
sqlmigrate
查看某个迁移文件在映射到数据库中的时候,转换成的sql语句。
-
-
根据已有的表自动生成模型
- 先在settings.py中配置好数据库相关信息。
- 使用
python manage.py inspectdb
将表转换为模型后的代码。 - 使用重定向将代码输出到指定的文件中。
python manage.py inspectdb > models.py
- 修正模型,新生成的模型有些地方不合适。那么需要重新配置一下:模型名、模型所属app、模型外键引用、让Django管理模型(将Meta下的managed=False)删掉。注意Meta中的db_table不要修改。
- 执行命令
python manage.py makemigrations
生成初始化的迁移脚本。方便后面通过ORM来管理表。 这时候还需要执行命令python manage.py migrate --fake-initial
-
-