模型层
查看orm内部sql语句的方法的方法
1.如果是queryset对象,那么可以点query直接查看该queryset的内部sql语句
2.在Django项目的配置文件中,配置一下参数即可实现所有的orm在查询的时候自动打印对应的sql语句
1LOGGING = { 2 'version': 1, 3 'disable_existing_loggers': False, 4 'handlers': { 5 'console':{ 6 'level':'DEBUG', 7 'class':'logging.StreamHandler', 8 }, 9 }, 10 'loggers': { 11 'django.db.backends': { 12 'handlers': ['console'], 13 'propagate': True, 14 'level':'DEBUG', 15 }, 16 } 17}
models.py
1from django.db import models 2 3# Create your models here. 4class Book(models.Model): 5 title = models.CharField(max_length=255) 6 price = models.DecimalField(max_digits=8,decimal_places=2) 7 publish_date = models.DateField(auto_now_add=True) 8 9 # 库存数 后加的,需要手动传值 10 kucun = models.IntegerField(null=True) 11 # 卖出数 后加的,需要手动传值 12 maichu = models.IntegerField(null=True) 13 14 publish = models.ForeignKey(to='Publish') # 默认是跟publish的主键字段做的一对多外键关联 15 authors = models.ManyToManyField(to='Author') 16 # 虚拟字段 1.自动创建第三张表 2.帮助orm跨表查询 17 18 def __str__(self): 19 return self.title 20 21class Publish(models.Model): 22 name = models.CharField(max_length=32) 23 addr = models.CharField(max_length=32) 24 # email = models.EmailField() # 就是varchar(254) 25 26 def __str__(self): 27 return self.name 28 29class Author(models.Model): 30 name = models.CharField(max_length=32) 31 age = models.IntegerField() 32 author_detail = models.OneToOneField(to='AuthorDetail') 33 34 def __str__(self): 35 return self.name 36class AuthorDetail(models.Model): 37 phone = models.BigIntegerField() 38 addr = models.CharField(max_length=64) 39 """ 40 models.py中的模型类__str__方法 必须返回一个字符串形式数据!!! 41 42 """ 43 def __str__(self): 44 return self.addr
基于models.py中表的查询方法(补充Q的高级用法末尾)
1from django.test import TestCase 2 3# Create your tests here. 4import os 5 6 7if __name__ == "__main__": 8 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day55.settings") 9 import django 10 django.setup() 11 """在下面就可以写针对某一个py文件的测试代码""" 12 from app01 import models 13 # 一对多的字段的增删改查 14 # 增 15 # publish_id传数字 16 # models.Book.objects.create(title='三国演义',price=189.99,publish_id=1) 17 # publish直接传出版社对象 18 # publish_obj = models.Publish.objects.filter(pk=2).first() 19 # models.Book.objects.create(title='红楼梦',price=999.99,publish=publish_obj) 20 21 # 改 22 # 传数字的 23 # models.Book.objects.filter(pk=1).update(publish_id=3) 24 # 传对象的 25 # publish_obj = models.Publish.objects.filter(pk=2).first() 26 # models.Book.objects.filter(pk=1).update(publish=publish_obj) 27 28 # 查 29 30 # 删 31 # models.Publish.objects.filter(pk=2).delete() # 默认都是级联更新 级联删除 32 33 34 # 多对多字段的增删改查 35 # 增 36 # 要给主键为1的书籍添加两个作者 37 # book_obj = models.Book.objects.filter(pk=1).first() 38 # print(book_obj.authors) # 对象点击多对多虚拟字段 会直接跨到多对多的第三张表 39 # book_obj.authors.add(1) 40 # book_obj.authors.add(2,3) 41 42 # author_obj = models.Author.objects.filter(pk=1).first() 43 # author_obj1 = models.Author.objects.filter(pk=2).first() 44 # author_obj2 = models.Author.objects.filter(pk=3).first() 45 # book_obj.authors.add(author_obj) 46 # book_obj.authors.add(author_obj1,author_obj2) 47 """ 48 add() 49 是给书籍添加作者 括号内既可以传数字也可以传对象 50 并且支持一次性传多个 逗号隔开即可 51 """ 52 53 # 改 54 # 将主键为1的书籍对象 作者修改为2,3 55 # book_obj = models.Book.objects.filter(pk=1).first() 56 # book_obj.authors.set([2,]) 57 # book_obj.authors.set([2,3]) 58 59 # author_obj = models.Author.objects.filter(pk=1).first() 60 # author_obj1 = models.Author.objects.filter(pk=2).first() 61 # author_obj2 = models.Author.objects.filter(pk=3).first() 62 # book_obj.authors.set([author_obj,]) 63 # book_obj.authors.set([author_obj, author_obj1, author_obj2]) 64 """ 65 set()括号内 需要传一个可迭代对象 66 可迭代对象中 可以是多个数字组合 67 也可以是多个对象组合 68 但是不要混着用!!! 69 """ 70 71 # 删 72 # book_obj = models.Book.objects.filter(pk=1).first() 73 # # book_obj.authors.remove(3) 74 # book_obj.authors.remove(1,2) 75 # author_obj = models.Author.objects.filter(pk=1).first() 76 # author_obj1 = models.Author.objects.filter(pk=2).first() 77 # author_obj2 = models.Author.objects.filter(pk=3).first() 78 # book_obj.authors.remove(author_obj) 79 # book_obj.authors.remove(author_obj1,author_obj2) 80 """ 81 remove()括号内既可以传数字 也可以传对象 82 并且支持传对个 逗号隔开即可 83 """ 84 85 # 将某本书跟作者的关系全部清空 86 # book_obj = models.Book.objects.filter(pk=1).first() 87 # book_obj.authors.clear() # 清空当前书籍与作者的所有关系 88 89 """ 90 add() 91 set() 92 remove() 93 上面三个都支持传数字 或者对象 并且可以传多个 但是set需要传可迭代对象 94 95 clear() 96 clear括号内不需要传任何参数 97 """ 98 99 # 跨表查询(******) 100 """ 101 正向与反向的概念 102 103 # 一对一 104 # 正向:author---关联字段在author表里--->authordetail 按字段 105 # 反向:authordetail---关联字段在author表里--->author 按表名小写 106 107 108 # 一对多 109 # 正向:book---关联字段在book表里--->publish 按字段 110 # 反向:publish---关联字段在book表里--->book 按表名小写_set.all() 因为一个出版社对应着多个图书 111 112 # 多对多 113 # 正向:book---关联字段在book表里--->author 按字段 114 # 反向:author---关联字段在book表里--->book 按表名小写_set.all() 因为一个作者对应着多个图书 115 116 117 正向查询按外键字段 118 反向查询按表名小写 119 """ 120 """基于对象的跨表查询(子查询:将一张表的查询结果当做另外一个查询语句的条件)""" 121 """ 122 强调:在书写orm语句的时候 跟写sql语句一样 123 不要尝试着 一次性写完 应该做到写一点看一点再一点 124 """ 125 # 1.查询书籍id是1 的出版社名称 126 # book_obj = models.Book.objects.filter(pk=1).first() 127 # print(book_obj.publish.name) 128 # print(book_obj.publish.addr) 129 130 # 2.查询书籍id是2 的作者姓名 131 # book_obj = models.Book.objects.filter(pk=2).first() 132 # print(book_obj.authors) # app01.Author.None 133 # print(book_obj.authors.all()) 134 # res = book_obj.authors.all() 135 # for r in res: 136 # print(r.name) 137 138 # 3.查询作者是jason的家庭住址 139 # author_obj = models.Author.objects.filter(name='jason').first() 140 # print(author_obj.author_detail.addr) 141 142 143 # 4.查询出版社是东方出版社出版的书籍 144 # publish_obj = models.Publish.objects.filter(name='东方出版社').first() 145 # # print(publish_obj.book_set) # app01.Book.None 146 # print(publish_obj.book_set.all()) 147 148 # 5.查询作者是jason的写过的所有的书籍 149 # author_obj = models.Author.objects.filter(name='jason').first() 150 # print(author_obj.book_set) # app01.Book.None 151 # print(author_obj.book_set.all()) 152 153 # 6.查询电话号码是130的作者姓名 154 # author_detail_obj = models.AuthorDetail.objects.filter(phone=130).first() 155 # print(author_detail_obj.author.name) 156 # print(author_detail_obj.author.age) 157 """ 158 当你反向查询的结果是多个的时候 就需要加_set 159 否则直接表明小写即可 160 """ 161 162 # 7.查询书籍id为1 的作者的电话号码 163 # book_obj = models.Book.objects.filter(pk=1).first() 164 # author_list = book_obj.authors.all() 165 # for author_obj in author_list: 166 # print(author_obj.author_detail.phone) 167 168 """基于双下划綫的跨表查询(连表操作) 169 left join 170 inner join 171 right join 172 union 173 """ 174 # 正向 175 # 1.查询jason作者的手机号 176 # res = models.Author.objects.filter(name='jason').values('author_detail__phone','author_detail__addr') 177 # print(res) 178 179 # res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone') 180 # print(res1) 181 182 183 # 查询jason这个作者的年龄和手机号 184 # 正向 185 # res = models.Author.objects.filter(name='jason').values('age','author_detail__phone') 186 # print(res) 187 # 反向 188 # res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age') 189 # print(res1) 190 191 192 # 查询手机号是130的作者年龄 193 # 正向 194 # res = models.AuthorDetail.objects.filter(phone=130).values('author__age') 195 # print(res) 196 # # 反向 197 # res1 = models.Author.objects.filter(author_detail__phone=130).values('age') 198 # print(res1) 199 200 # 查询书籍id是1 的作者的电话号码 201 # res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone') 202 # res1 = models.Book.objects.filter(pk=1).values('外键字段1__外键字段2__外键字段3__普通字段') 203 # print(res) 204 """只要表里面有外键字段 你就可以无限制跨多张表""" 205 206 # 1.查询出版社为北方出版社的所有图书的名字和价格 207 # res = models.Publish.objects.filter(name='北方出版社').values('book__title','book__price') 208 # print(res) 209 210 # 2.查询北方出版社出版的价格大于19的书 211 # res = models.Book.objects.filter(price__gt=19,publish__name='北方出版社').values('title','publish__name') 212 # print(res) 213 214 215 # 聚合查询(aggregate) 216 # 1.统计所有书的总价格 217 # from django.db.models import Max,Min,Count,Avg,Sum 218 # 219 # # res = models.Book.objects.aggregate(Sum('price')) 220 # res1 = models.Book.objects.aggregate(Avg('price')) 221 # res2 = models.Book.objects.aggregate(Count('price')) 222 # res3 = models.Book.objects.aggregate(Max('price')) 223 # res4 = models.Book.objects.aggregate(Min('price')) 224 # res5 = models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price')) 225 # print(res5) 226 # print(res) 227 # print(res1) 228 # print(res2) 229 230 231 # 分组查询 232 # 统计每一本书的作者个数 233 from django.db.models import Max, Min, Count, Avg, Sum 234 # res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title') 235 # print(res) 236 237 # 统计出每个出版社卖的最便宜的书的价格 238 # res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp') 239 # print(res) 240 241 # 统计不止一个作者的图书 242 # res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1) 243 # print(res) 244 245 """ 246 只要是queryset对象 就可以无限制的调用queryset对象的方法!!! 247 最最常用的就是对一个已经filter过滤完的数据 再进行更细化的筛选 248 249 """ 250 251 # 查询各个作者出的书的总价格 252 # res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp') 253 # print(res) 254 255 256 #F查询的本质就是从数据库中获取某个字段的值 257 # 查询库存数大于卖出数的书籍 258 """之前查询等号后面的条件都是我们认为输入的 259 现在变成了需要从数据库中获取数据放在等号后面 260 """ 261 from django.db.models import F 262 # res = models.Book.objects.filter(kucun__gt=F('maichu')) 263 # print(res) 264 265 266 # 将书籍库存数全部增加1000 267 # models.Book.objects.update(kucun=F('kucun')+1000) 268 269 # 把所有书名后面加上'新款' 270 271 # from django.db.models.functions import Concat 272 # from django.db.models import Value 273 # 274 # ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款'))) 275 # models.Book.objects.update(title = F('title')+'新款') # 不能这么写 276 277 278 # Q查询 279 from django.db.models import Q 280 # 查询书籍名称是三国演义或者价格是444.44 281 # res = models.Book.objects.filter(title='三国演义',price=444.44) # filter只支持and关系 282 # res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444)) # 如果用逗号 那么还是and关系 283 # res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444)) 284 # res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444)) 285 # print(res2) 286 287 288 # Q高级用法 289 q = Q() 290 q.connector = 'or' # 修改查询条件的关系 默认是and 291 q.children.append(('title__contains','三国演义')) # 往列表中添加筛选条件 292 q.children.append(('price__gt',444)) # 往列表中添加筛选条件 293 res = models.Book.objects.filter(q) # filter支持你直接传q对象 但是默认还是and关系 294 print(res)
自定义char字段
1 class MyCharField(models.Field): 2 def __init__(self,max_length,*args,**kwargs) 3 self.max_length = max_length 4 super().__init__(max_length=max_length,*args,**kwargs) 5 6 def db_type(self,connection): 7 return 'char(%s)'%self.max_length 8 9 class User(models.Model): 10 username = MyCharField(max_length=32)