一 模型层常用字段和参数
1.模型表建立常用字段

1. AutoField:int自增主键列。必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列 id = models.AutoField(primary_key=True) 2.CharField:字符串,相当于varchar。必须提供max_length参数,不能超过255。 title = models.CharField(max_length=255) 3.IntegerField:整数类型,范围在 -2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存,) kucun = models.IntegerField(null=True) # null参数可不填 4.DecimalField:浮点类型。参数1 max_digits表示总共的位数,参数2 decimal_places表示小数的位数 price = models.DecimalField(max_digits=8,decimal_places=2) 5.DateField: create_time = models.DateField() # 不指定auto_now或auto_now_add时,需要自己传参数 关键性的参数: 1.auto_now:每次操作数据 都会自动刷新当前操作的时间 2.auto_now_add:在创建数据的时候 会自动将创建时间记录下来 后续的修改不会影响该字段
2.字段参数

null 用于表示某个字段可以为空。 unique 如果设置为unique=True 则该字段在此表中必须是唯一的 。 db_index 如果db_index=True 则代表着为此字段设置索引。 default 为该字段设置默认值。
3.表与表之间的关系字段
https://www.cnblogs.com/tfzz/p/11537119.html
二 设置Django打印sql语句
在settings.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',
},
}
}
三 单表双下滑线查询(相当于新的过滤条件)

1.大于:__gt 小于:__lt 大于等于:__gte 小于等于:__lte #价格 大于 小于 大于等于 小于等于 filter(price__gt='90') filter(price__lt='90') filter(price_gte='90') filter(price_lte='90') 2.__in:存在与某几个条件中(相当于或的关系) filter(price__in=['11','22','33']) models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in 3. __range 在某个范围内(顾头又顾尾) filter(price__range=[50,90]) 4. __contains模糊查询 models.Tb1.objects.filter(name__contains="ven") # 获取name字段包含"ven"的,区分大小写 models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不区分 5.__startswith,__istartswith以什么开头(区分大小写和不区分) 6.__endswith, __iendswith以什么结尾(区分大小写和不区分) 7.date字段可以通过在其后加__year,__month,__day等来获取date的特点部分数据 filter(create_time__year='2017') # 查询2017年的数据
四 多表操作
1.一对多关系 :一对多字段的增删改查
以(Book表 和出版社Publish表为例,一对多关系,为publish外键)为例:

from django.db import models
class Book(models.Model):
title = models.CharField(max_length=255)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish_date = models.DateField(auto_now_add=True)
# 库存数
kucun = models.IntegerField(null=True)
# 卖出数
maichu = models.IntegerField(null=True)
publish = models.ForeignKey(to='Publish') # 默认是跟publish的主键字段做的一对多外键关联
authors = models.ManyToManyField(to='Author')
# 虚拟字段 1.自动创建第三张表 2.帮助orm跨表查询
def __str__(self):
return self.title
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
# email = models.EmailField() # 就是varchar(254)
def __str__(self):
return self.name

1.增: 针对外键关联的字段 两种添加方式 第一种通过 外键字段_id=值 models.Book.objects.create(title='三国演义',price=189.99,publish_id=1) 第二种通过 外键字段=对象 publish_obj = models.Publish.objects.filter(pk=2).first() models.Book.objects.create(title='红楼梦',price=999.99,publish=publish_obj) 2.删 models.Publish.objects.filter(pk=2).delete() # 默认都是级联更新 级联删除 3.改 第一种通过 外键字段_id=值 models.Book.objects.filter(pk=1).update(publish_id=3) 第二种通过 外键字段=对象 publish_obj = models.Publish.objects.filter(pk=2).first() models.Book.objects.filter(pk=1).update(publish=publish_obj) 4.查 .filter() .all()
2.多对多关系:多对多字段的 增删改查
以(Book表 和作者Author表为例,多对多关系authors为外键)为例:
注意:对象点击多对多虚拟字段 会直接跨到多对多的第三张表

from django.db import models
# Create your models here.
class Book(models.Model):
title = models.CharField(max_length=255)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish_date = models.DateField(auto_now_add=True)
# 库存数
kucun = models.IntegerField(null=True)
# 卖出数
maichu = models.IntegerField(null=True)
publish = models.ForeignKey(to='Publish') # 默认是跟publish的主键字段做的一对多外键关联
authors = models.ManyToManyField(to='Author')
# 虚拟字段 1.自动创建第三张表 2.帮助orm跨表查询
def __str__(self):
return self.title
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDetail')

1.增:add可以传作者id数字,也可以直接传作者对象,并且支持传多个位置参数(不要混着用)
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.add(1)
book_obj.authors.add(2,3)
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
author_obj2 = models.Author.objects.filter(pk=3).first()
book_obj.authors.add(author_obj)
book_obj.authors.add(author_obj1,author_obj2)
2.删:remove()括号内既可以传数字 也可以传对象 ,并且支持传对个 逗号隔开即可
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.remove(3)
book_obj.authors.remove(1,2)
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
author_obj2 = models.Author.objects.filter(pk=3).first()
book_obj.authors.remove(author_obj)
book_obj.authors.remove(author_obj1,author_obj2)
3.改:set()括号内 需要传一个可迭代对象 ,可迭代对象中 可以是多个数字组合,也可以是多个对象组合,但是不要混着用!!!
# 将主键为1的书籍对象 作者修改为2,3
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.set([2,])
book_obj.authors.set([2,3])
# author_obj = models.Author.objects.filter(pk=1).first()
# author_obj1 = models.Author.objects.filter(pk=2).first()
# author_obj2 = models.Author.objects.filter(pk=3).first()
# book_obj.authors.set([author_obj,])
# book_obj.authors.set([author_obj, author_obj1, author_obj2])
4.查
# 将某本书跟作者的关系全部清空
# book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.clear() # 清空当前书籍与作者的所有关系
5.总结:
"""
add()
set()
remove()
上面三个都支持传数字 或者对象 并且可以传多个 但是set需要传可迭代对象
clear()
clear括号内不需要传任何参数
"""
3.正向和反向跨表查询
正向查询:当前表中存在着另一张要查询表的外键,可以通过 .外键 跨表查询称之为正向查询。
反向查询:当前表中不存在着另一张要查询表的外键,可以通过 .另一张表名 跨查询称之为反向查询。
示例表

from django.db import models
# Create your models here.
class Book(models.Model):
title = models.CharField(max_length=255)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish_date = models.DateField(auto_now_add=True)
# 库存数
kucun = models.IntegerField(null=True)
# 卖出数
maichu = models.IntegerField(null=True)
publish = models.ForeignKey(to='Publish') # 默认是跟publish的主键字段做的一对多外键关联
authors = models.ManyToManyField(to='Author')
# 虚拟字段 1.自动创建第三张表 2.帮助orm跨表查询
def __str__(self):
return self.title
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
# email = models.EmailField() # 就是varchar(254)
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDetail')
def __str__(self):
return self.name
class AuthorDetail(models.Model):
phone = models.BigIntegerField()
addr = models.CharField(max_length=64)
"""
models.py中的模型类__str__方法 必须返回一个字符串形式数据!!!
"""
def __str__(self):
return self.addr
#基于对象的正反向查询
正向: 对象.关联字段(外键).字段 /all()
反向: 对象.表名小写(_set).字段/all()
要点:先拿到对象,再通过对象去查对应的外键字段,分两步

正向查询
1.查询书籍id是1 的出版社名称(一对多) 书籍---->出版社
book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.publish.name) # 对象点外键字段直接跨到另一张表中
print(book_obj.publish.addr)
2.查询书籍id是2 的作者姓名(多对多) 书籍———》作者
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.authors) # app01.Author.None
print(book_obj.authors.all())
res = book_obj.authors.all()
for r in res:
print(r.name)
反向查询
1.查询出版社是东方出版社出版的书籍(一对多) 出版社———》书籍
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
# print(publish_obj.book_set) # app01.Book.None
print(publish_obj.book_set.all())
6.查询电话号码是130的作者姓名 (一对一) 信息表———》作者
author_detail_obj = models.AuthorDetail.objects.filter(phone=130).first()
print(author_detail_obj.author.name)
print(author_detail_obj.author.age)
#正向和反向查询时结果可能为多个时加上 .all(),反向还要表名小写:表名小写_set.all()

# 5.查询作者是jason的写过的所有的书籍(多对多) 作者———》 书
# author_obj = models.Author.objects.filter(name='jason').first()
# print(author_obj.book_set) # app01.Book.None
# print(author_obj.book_set.all())
#基于双下换线的正反向查询
正向:按字段,跨表可以在filter,也可以在values中
反向:按表名小写,跨表可以在filter,也可以在values中
正向:关联字段(外键)__字段
反向:表名小写__字段

1.查询jason作者的手机号(一对一) 作者——》信息
正向:
res=models.Author.objects.filter(name='jason').values('author_detail__phone','author_detail__addr')
print(res)
反向:
res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone')
print(res1)
查询jason这个作者的年龄和手机号 (一对一) 作者——》信息
正向:
res=models.Author.objects.filter(name='jason').values('age','author_detail__phone') # 年龄在本表中不需要跨表,手机号不在需要跨表
print(res)
反向:
res1=models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age') # 手机号在本表中不需要跨表,年龄不在需要跨表
print(res1)
2.查询手机号是130的作者年龄(一对一)
正向:
res = models.AuthorDetail.objects.filter(phone=130).values('author__age')
print(res)
反向:
res1 = models.Author.objects.filter(author_detail__phone=130).values('age')
print(res1)
3.查询书籍id是1 的作者的电话号码
res=models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
# res1 = models.Book.objects.filter(pk=1).values('外键字段1__外键字段2__外键字段3__普通字段')
print(res)
"""只要表里面有外键字段 你就可以无限制跨多张表"""
4. # 1.查询出版社为北方出版社的所有图书的名字和价格
# res = models.Publish.objects.filter(name='北方出版社').values('book__title','book__price')
# print(res)
# 2.查询北方出版社出版的价格大于19的书
# res = models.Book.objects.filter(price__gt=19,publish__name='北方出版社').values('title','publish__name')
# print(res)
4.聚合查询(aggregate)
from django.db.models import Max,Min,Count,Avg,Sum
res = models.Book.objects.aggregate(Sum('price'))
res1 = models.Book.objects.aggregate(Avg('price'))
res2 = models.Book.objects.aggregate(Count('price'))
res3 = models.Book.objects.aggregate(Max('price')) res4 = models.Book.objects.aggregate(Min('price'))
res5=models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price'))
print(res5)
print(res)
print(res1)
print(res2)
5.分组
# 分组查询
# 统计每一本书的作者个数
from django.db.models import Max, Min, Count, Avg, Sum
# res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title') # 依据Book分组,author_num为别名
# print(res)
# 统计出每个出版社卖的最便宜的书的价格
# res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp')
# print(res)
# 统计不止一个作者的图书
# res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)
# print(res)
"""
只要是queryset对象 就可以无限制的调用queryset对象的方法!!!
最最常用的就是对一个已经filter过滤完的数据 再进行更细化的筛选
"""
# 查询各个作者出的书的总价格
# res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp')
# print(res)
6.F查询(获取字段的值)
#F查询的本质就是从数据库中获取某个字段的值
# 查询库存数大于卖出数的书籍
"""之前查询等号后面的条件都是我们认为输入的
现在变成了需要从数据库中获取数据放在等号后面
"""
from django.db.models import F
res = models.Book.objects.filter(kucun__gt=F('maichu'))
print(res)
# 将书籍库存数全部增加1000# models.Book.objects.update(kucun=F('kucun')+1000)# 把所有书名后面加上'新款'# from django.db.models.functions import Concat# from django.db.models import Value## ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))# models.Book.objects.update(title = F('title')+'新款') # 不能这么写
7.Q查询(更改条件之间的关系)
# Q查询
from django.db.models import Q
# 查询书籍名称是三国演义或者价格是444.44
# res = models.Book.objects.filter(title='三国演义',price=444.44) # filter只支持and关系
# res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444)) # 如果用逗号 那么还是and关系
# res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444)) # 或的关系
# res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444)) # ~非的关系
# print(res2)
# Q高级用法
q = Q()
q.connector = 'or' # 修改查询条件的关系 默认是and
q.children.append(('title__contains','三国演义')) # 往列表中添加筛选条件
q.children.append(('price__gt',444)) # 往列表中添加筛选条件
res = models.Book.objects.filter(q) # filter支持你直接传q对象 但是默认还是and关系
print(res)
