Django链接MySQL
"""django默认使用自带的sqlite3"""
1.配置文件修改配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '库名', # 一定要事先创建好才能指定
'HOST':'127.0.0.1',
'PORT':3306, # MySQL默认端口号3306
'USER':'用户名',
'PASSWORD':'密码',
'CHARSET':'utf8'
}
}
2.在项目文件夹或者应用文件夹内的__init__.py文件中书写固定的代码
import pymysql
pymysql.install_as_MySQLdb()
Django orm
orm:对象关系映射
orm目的就是为了能够让不懂SQL语句的人通过python面向对象的知识点也能够轻松自如的操作数据库
缺陷:sql封装死了,有时候查询速度很慢
类 >>> 表
对象 >>> 表里面的数据
对象点属性 >>> 字段对应的值
1.我们的模型类需要写在应用下的models.py文件中
class User(models.Model):
# id int primary key auto_increment
id = models.AutoField(primary_key=True)
# name varchar(32)
name = models.CharField(max_length=32) # CharField必须要加max_length参数
# age int
age = models.IntegerField()
****************************************************************************
2.数据库迁移命令
1.将数据库修改操作先记录到小本本上(对应应用下的migrations文件夹)
python3 manage.py makemigrations
2.真正的执行数据库迁移操作
python3 manage.py migrate
# 只要动了models.py中跟数据库相关的代码就必须重新执行上述两条命令
****************************************************************************
3.针对主键字段
class User1(models.Model):
# 如果你不指定主键 那么orm会自动帮你创建一个名为id的主键字段
# 如果你想让主键字段名不叫id 叫uid、sid、pid等则需要自己手动指定
username = models.CharField(max_length=32)
orm数据库同步命令
"""
数据库里面已经有一些表,我们如何通过django orm操作?
1.照着数据库表字段自己在models.py
数据需要自己二次同步
2.django提供的反向同步
"""
1.先执行数据库迁移命令 完成链接
python manage.py makemigrations
2.查看代码
python manage.py inspectdb
orm字段的增删改
# 增
pwd = models.IntegerField('密码',null=True) # 该字段可以为空
is_delete = models.IntegerField(default=0) # 默认值
# 改
直接改代码然后执行数据库迁移命令即可
# 删
注释掉代码然后执行数据库迁移命令即可
orm常用和非常用字段
常用
AutoField # 自增列,如果没有的话,默认会生成一个名称为 id 的列。
# 如果要显式的自定义一个自增列,必须设置primary_key=True
IntegerField # 整形
FloatField # 浮点类型
CharField # 字符串字段
DateField # 日期类型
auto_now=True # 保存时自动设置该字段为现在日期,最后修改日期
auto_now_add=True # 当该对象第一次被创建是自动设置该字段为现在日期,创建日期。
DateTimeField # 日期时间类型
auto_now=True # 保存时自动设置该字段为现在日期,最后修改日期
auto_now_add=True # 当该对象第一次被创建是自动设置该字段为现在日期,创建日期。
非常用
BooleanField # 布尔类型
TextField # 大文本
FileField # 文件
upload_to='' # 上传文件的本地文件系统路径
EmailField # 带有检查Email合法性的CharField
GenericIPAddressField # 带有检查IP地址合法性的CharField
URLField # 带有URL合法性校验的CharField
orm字段参数
null # 是否可以为空
primary_key # 主键,对AutoField设置主键后,就会代替原来的自增 id 列
unique # 是否唯一
db_index # 是否给该字段建索引
default # 默认值为
max_length # 字段长度
choices
-在model表模型定义的时候给某个字段指定choice
sex_choice=((1,'男'),(2,'女'),(0,'未知'))
sex =models.IntegerField(default=1,choices=sex_choice)
-在使用的时候,直接取出中文
对象.get_sex_display()
了解
verbose_name Admin中显示的字段名称
blank Admin中是否允许用户输入为空
editable Admin中是否可以编辑
help_text Admin中该字段的提示信息
choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
orm数据的增删改查
# 1.查询数据
# select * from user where name=username;
user_obj = models.User.objects.filter(name=username).first()
# 2.添加数据
# insert into user(name,pwd) values(username,password);
models.User.objects.create(name=username,pwd=password)
# 3.查询所有的数据
# select * from user;
models.User.objects.all() # [obj1,obj2,obj3,obj4]
# 4.修改数据
方法一:
models.User.objects.filter(id=edit_id).update(name=username,pwd=password)
方法二:
edit_obj.name = username
edit_obj.pwd = password
edit_obj.save()
# 5.删除数据
models.User.objects.filter(id=delete_id).delete()
orm创建外键关系
# ORM针对外键字段的创建位置
一对多
推荐建在多的一方
一对一
建在任何一方都可以,但是推荐建在查询频率较高的表中
多对多
1.自己建表
2.建在任何一方都可以,但是推荐建在查询频率较高的表中
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2) # 总共8位 小数占2位
# 出版社外键
publish = models.ForeignKey(to='Publish') # 默认就是主键
"""自动在外键字段后面加_id后缀"""
# 作者外键
authors = models.ManyToManyField(to='Author') # 自动帮你创建书籍和作者的第三张表
"""虚拟字段不会在表中实例化出来 而是告诉ORM创建第三张关系表"""
class Publish(models.Model):
title = models.CharField(max_length=32)
email = models.EmailField()
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDetail')
"""自动在外键字段后面加_id后缀"""
class AuthorDetail(models.Model):
phone = models.BigIntegerField()
addr = models.CharField(max_length=128)
ForeignKey参数
to # 对那张表
to_field # 对表中的某个字段
related_name # 反向操作时,使用的字段名,用于代替原反向查询时的’表名_set’
related_query_name # 反向查询操作时,使用的连接前缀,用于替换表名
on_delete #当删除关联表中的数据时,当前表与其关联的行的行为。
models.CASCADE # 删除关联数据,与之关联也删除
models.DO_NOTHING # 删除关联数据,什么都不做
models.PROTECT # 删除关联数据,引发错误ProtectedError
models.SET_NULL # 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
models.SET_DEFAULT # 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
models.SET # 删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
db_constraint
True:建立外键,默认是True
False:不建立外键
外键是否建立:
-好处:不会出现脏数据
-坏处:插入的时候,效率低
-企业中:通常不建立,程序员控制
ManyToManyField字段参数
db_table # 指定第三张表的名字
to # 关联的表
related_name # 反向操作时,使用的字段名,用于代替原反向查询时的’表名_set’
related_query_name # 反向查询操作时,使用的连接前缀,用于替换表名
through # 手动创建第三张表,指定通过哪个表
through_fields # 关联字段是什么
手动创建第三张表
多对多关系建立的三种方式
第一种:自动创建(常用:第三张表没有其他字段)
第二种:手动创建第三张表(比较常用:第三张表有多余字段)
第三种:完全手动写第三张表
# 第一种:
class Book(models.Model):
title = models.CharField(max_length=32, verbose_name="书名")
# 通过ORM自带的ManyToManyField自动创建第三张表
class Author(models.Model):
name = models.CharField(max_length=32, verbose_name="作者姓名")
books = models.ManyToManyField(to="Book", related_name="authors")
# 第二种
class Book1(models.Model):
title = models.CharField(max_length=32, verbose_name="书名")
# 自己创建第三张表,并通过ManyToManyField指定关联
class Author1(models.Model):
name = models.CharField(max_length=32, verbose_name="作者姓名")
books = models.ManyToManyField(
to="Book1", through="Author2Book", through_fields=("author", "book")
)
# through_fields 元组的第一个值是ManyToManyField所在的表去中间表通过那个字段,就写在第一个位置
class Author2Book(models.Model):
author = models.ForeignKey(to="Author1")
book = models.ForeignKey(to="Book1")
# 第三种
class Book1(models.Model):
title = models.CharField(max_length=32, verbose_name="书名")
class Author1(models.Model):
name = models.CharField(max_length=32, verbose_name="作者姓名")
# 自己创建第三张表,分别通过外键关联书和作者
class Author2Book1(models.Model):
author = models.ForeignKey(to="Author")
book = models.ForeignKey(to="Book")
多对多操作的api
book.authors.add() # 添加关系
book_obj.authors.remove() # 将某个特定的对象从被关联对象集合中去除。
book_obj.authors.clear() # 清空被关联对象集合
book_obj.authors.set() # 先清空再设置
# 在每一个模型类中都可以写
class Meta: #元信息
db_table='mypublish' #表名
index_together=('name','city') # 多个字段联合索引
unique_together=('name','city') # 联合唯一
ordering=('nid', ) # 默认以哪个字段排序
原生sql
res = models.Author.objects.raw('select * from app01_book where nid>1')
for book in res:
print(book.price)
# 执行原生sql,跟对象类型无关了,查出什么字段,可以直接使用该字段
orm单表查询关键字
QuerySet对象方法
query # 查看orm内部对应的SQL语句
# 增
res = models.Books.objects.create(title='西游记',price=687.90)
print(res.title)
'''create返回值就是当前被创建的数据对象'''
# 查
res = models.Books.objects.all()
print(res.query)
res = models.Books.objects.filter()
print(res.query)
res = models.Books.objects.filter(title='jason')
print(res)
"""filter括号内可以放多个参数 默认是and关系 推荐使用 条件不符合不会报错"""
res1 = models.Books.objects.get(title='jason')
print(res1)
"""get括号内可以放多个参数 默认是and关系 不推荐使用 条件不符合直接报错"""
# 改
res = models.Books.objects.filter(pk=1).update(price=666.66)
print(res) # 返回值是受影响的行数
book_obj = models.Books.objects.filter(pk=2).first()
book_obj.price = 999.66
book_obj.save() # 效率低(所有字段重新写一遍)
"""pk能够自动查找到当前表的主键字段 我们不需要查看当前表主键字段名"""
# 删
models.Books.objects.filter(pk=1).delete()
.first() # 取第一个数据对象
res = models.Books.objects.all().first()
res1 = models.Books.objects.all()[0]
res2 = models.Books.objects.all()[0:2]
print(res,res1,res2)
"""QuerySet对象还支持切片操作 但是只能填正数"""
.last() # 取最后一个数据对象
res = models.Books.objects.all().last()
print(res)
.values() # 获取数据指定字段的值
res = models.Books.objects.all().values('title','publish_time')
res1 = models.Books.objects.values('title','publish_time')
print(res,res1)
"""all()加不加都表示所有数据 values获取的结果 类似于列表套字典"""
.values_list() # 获取数据指定字段的值
res = models.Books.objects.values_list('title', 'publish_time')
print(res)
"""values_list获取的结果 类似于列表套元组"""
.order_by() # 排序
res = models.Books.objects.order_by('price') # 默认是升序
print(res)
res1 = models.Books.objects.order_by('-price') # 减号降序
print(res1)
.count() # 计数
res = models.Books.objects.count() # 统计数据条数
print(res)
.distinct() # 去重
res = models.Books.objects.all().distinct()
res1 = models.Books.objects.values('title').distinct()
print(res1)
"""去重的前提是数据必须是一模一样 一定不能忽略主键"""
.exclude() # 排除什么什么在外 取反操作
res = models.Books.objects.exclude(title='西游记')
print(res.query)
.reverse() # 反转
res = models.Books.objects.all()
res1 = models.Books.objects.reverse()
res2 = models.Books.objects.order_by('price').reverse()
print(res)
print(res1)
print(res2)
"""reverse需要先排序之后才能反转"""
.exists() 判断是否有数据 返回布尔值
res = models.Books.objects.all().exists()
print(res)
神奇的双下划綫查询(范围查询)
__gt # 大于
查询价格大于700的书籍
models.Books.objects.filter(price__gt=700)
__lt # 小于
查询价格小于700的书籍
models.Books.objects.filter(price__lt=700)
__gte、__lte # 大于等于、小于等于
价格大于等于700 小于等于700
models.Books.objects.filter(price__gte=700)
models.Books.objects.filter(price__lte=700)
__in # 在这之中
查询价格要么是40 要么是50 要么是60
models.Books.objects.filter(price__in=[40,50,60])
__range # 在什么之间
查询价格在500到800之间的
models.Books.objects.filter(price__range=(500,800))
__contains # 包含
查询书名中包含字母s的书
models.Books.objects.filter(title__contains='s') # 区分大小写
models.Books.objects.filter(title__icontains='s') # 区分大小写
__year、__month # 筛选年、月
查询出版日期是2021年3月的书
models.Books.objects.filter(publish_time__year=2021,publish_time__month=3)
跨表查询理论
正向
外键字段在谁那儿,谁查另外的人就是正向
反向
没有外键字段
# 就是判断你是否有关联的外键字段
"""
正向查询按外键字段
反向查询按表名小写加_set
"""
基于对象的跨表查询
# 子查询
"""
1.先查询出一个对象
2.基于对象点正反向字段
"""
查询神雕侠侣对应的作者
book_obj = models.Book.objects.filter(title='神雕侠侣').first()
res = book_obj.authors.all()
查询东方出版社出版过的书籍
author_obj = models.Author.objects.filter(name='jason').first()
res = author_obj.book_set.all()
基于双下划线的跨表查询
查询神雕侠侣对应的作者名字
res = models.Book.objects.filter(title='神雕侠侣').values('authors__name')
res = models.Author.objects.filter(book__title='神雕侠侣').values('name','age')
聚合查询
from django.db.models import Sum,Avg,Max,Min,Count
1 聚合函数,sum,max,min,count,avg
2 把聚合结果字段重命名
res=models.Book.objects.all().aggregate(aaa=Sum('price'))
F查询
F 查询:取出某个字段对应的值
from django.db.models import F
查询评论数大于阅读数的书籍
res=models.Book.objects.filter(commit_num__gt=F('read_num'))
print(res)
把所有图书价格+1
res=models.Book.objects.all().update(price=F('price')+1)
print(res) # 影响额行数
Q查询
Q 查询:构造出 与&、或|、非~
查询名字叫红楼梦并且者价格大于100的书
models.Book.objects.filter(name='红楼梦'&price__gt=100)
查询名字叫红楼梦或者价格大于100的书
models.Book.objects.filter(Q(name='红楼梦')|Q(price__gt=100))
查询名字不是红楼梦,并且价格大于100的书
models.Book.objects.filter(~Q(name='红楼梦')&Q(price__gt='100'))
分组查询
annotate() 内写聚合函数
values在前,表示group by 的字段
values在后,表示取字段
filter在前,表示where条件
filter在后,表示having
查询出版社id大于1的出版社id,以及出书平均价格
models.Book.objects.values('publish_id').filter(publish_id__gt=1).annotate(price_ave=Avg('price')).values('publish_id','price_ave')
django查看原生sql
1 queryset对象.query
2 通过日志,如下,配置到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',
},
}
}
Djago admin的使用
1 后台管理,方便我们快速的录入书籍
2 使用方法:
第一步:在admin.py 中把要使用的表注册
from app01 import models
admin.site.register(models.Book)
admin.site.register(models.Author)
admin.site.register(models.AuthorDatail)
admin.site.register(models.Publish)
第二步:创建个超级管理员
python3 manage.py createsuperuser
输入用户名,输入密码
第三步:登录,录入书籍
-http://127.0.0.1:8000/admin/