前期准备
#在进行一系列的表查询的之前,做表#在models下from django.db import models# Create your models here.class User(models.Model):name = models.CharField(max_length=32)age = models.IntegerField()register_time = models.DateField()class Book(models.Model):#书title = models.CharField(max_length=32)price = models.DecimalField(max_digits=8,decimal_places=2)publish_date = models.DateField(auto_now=True)#一对多publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)#多对多authors = models.ManyToManyField(to='Author')class Publish(models.Model):#出版社name = models.CharField(max_length=32)addr = models.CharField(max_length=32)email = models.EmailField()# varchar(254) 该字段类型不是给models看的 而是给后面我们会学到的校验性组件看的class Author(models.Model):#作者name = models.CharField(max_length=32)age = models.IntegerField()#一对一authordetail = models.OneToOneField(to='AuthorDetail',on_delete=models.CASCADE)class AuthorDetail(models.Model):#作者详情phone = models.BigIntegerField()addr = models.CharField(max_length=64)
测试环境准备
"""当你只是想测试django中的某一个py文件内容 那么你可以不用书写前后端交互的形式而是直接写一个测试脚本即可脚本代码无论是写在应用下的tests.py还是自己单独开设py文件都可以"""# 测试环境的准备 去manage.py中拷贝前四行代码 然后自己写两行如果是2.x版本要将def改成if __name__ == "__main__":import osimport sysif __name__ == "__main__":os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day64.settings")import djangodjango.setup()# 在这个代码块的下面就可以测试django里面的单个py文件了
单表操作
django自带的sqlite3数据库对日期格式不是很敏感 处理的时候容易出错'''pk的意义:主键--->可以说是 primary_key 的缩写pk会自动查找到当前表的主键字段 指代的就是当前表的主键字段用了pk之后 你就不需要指代当前表的主键字段到底叫什么了uidpidsid...'''#增方法一:res = models.User.objects.create(name='wuhu',age=50,register_time=2020-10-5)方法二:ctime = datetime.datetime.now()user_obj = models.User(name='one',age=15,register_time=ctime)user_obj.save()#删方法一:res = models.User.objects.filter(pk=6).delete()print(res)方法二:user_obj = models.User.objects.filter(pk=5)user_obj.delete()#改方法一:res = models.User.objects.filter(pk=4).update(age=21)方法二:user_obj2 = models.User.objects.get(pk=4)user_obj = models.User.objects.filter(pk=4).first()user_obj.age=21user_obj.save()'''get和filter 都能拿到对象,前者是直接拿到对象,后者是有个列表套着,需要通过方法取出来虽然get比filter方便,能够直接拿到对象,但是如果没有数据对象不存在,就会报错而filter不会,他找不到会返回一个空列表,不会报错出于程序原则考虑,使用filter可以分别print get方法和filter方法来验证'''
必知必会方法13条
# 必知必会13条1.all() 查询所有数据2.filter() 带有过滤条件的查询3.get() 直接拿数据对象 但是条件不存在直接报错4.first() 拿queryset里面第一个元素5.last() queryset里面最后一个元素6.values() 可以指定获取的数据字段 --->列表套字典7.values_list() 列表套元祖8.distinct() 去重9.order_by() 排序10.reverse() 反转的前提是 数据已经排过序了11.count() 统计当前数据的个数12.exclude() 排除在外13.exists() 基本用不到因为数据本身就自带布尔值 返回的是布尔值示范:# 1.all() 查询所有数据# 2.filter() 带有过滤条件的查询# 3.get() 直接拿数据对象 但是条件不存在直接报错# 4.first() 拿queryset里面第一个元素# res = models.User.objects.all().first()# print(res)# 5.last()# res = models.User.objects.all().last()# print(res)# 6.values() 可以指定获取的数据字段 select name,age from ... 列表套字典# res = models.User.objects.values('name','age') # <QuerySet [{'name': 'jason', 'age': 18}, {'name': 'egonPPP', 'age': 84}]># print(res)# 7.values_list() 列表套元祖# res = models.User.objects.values_list('name','age') # <QuerySet [('jason', 18), ('egonPPP', 84)]># print(res)# """# # 查看内部封装的sql语句# 上述查看sql语句的方式 只能用于queryset对象# 只有queryset对象才能够点击query查看内部的sql语句## """# 8.distinct() 去重# res = models.User.objects.values('name','age').distinct()# print(res)"""去重一定要是一模一样的数据如果带有主键那么肯定不一样 你在往后的查询中一定不要忽略主键"""# 9.order_by()# res = models.User.objects.order_by('age') # 默认升序# res = models.User.objects.order_by('-age') # 降序## print(res)# 10.reverse() 反转的前提是 数据已经排过序了 order_by()# res = models.User.objects.all()# res1 = models.User.objects.order_by('age').reverse()# print(res,res1)# 11.count() 统计当前数据的个数# res = models.User.objects.count()# print(res)# 12.exclude() 排除在外# res = models.User.objects.exclude(name='jason')# print(res)# 13.exists() 基本用不到因为数据本身就自带布尔值 返回的是布尔值# res = models.User.objects.filter(pk=10).exists()# print(res)
查看内部sql语句的方式
#方法1:res = models.User.objects.values_list('name','age')print(res.query)#会返回QuerySet对象的查询语句且只有queryset对象才能够点击query查看内部的sql语句# 方式2:所有的sql语句都能查看# 去配置文件中配置一下即可LOGGING = {'version': 1,'disable_existing_loggers': False,'handlers': {'console':{'level':'DEBUG','class':'logging.StreamHandler',},},'loggers': {'django.db.backends': {'handlers': ['console'],'propagate': True,'level':'DEBUG',},}}
双下划线查询
#双下划线查询注:使用的皆为user表# 1 年龄大于18岁的数据第一个res = models.User.objects.filter(age__gt=18)print(res)# 2 年龄小于35岁的数据res = models.User.objects.filter(age__lt=35)print(res)# 大于等于res = models.User.objects.filter(age__gte=18)print(res)# 小于等于res = models.User.objects.filter(age__lte=19)print(res)# 年龄是18 或者 32 或者40res = models.User.objects.filter(age__in=[40,18,32])print(res)# 年龄在18到40岁之间的 首尾都要res = models.User.objects.filter(age__range=[18,40])print(res)# 查询出名字里面含有s的数据 模糊查询 区分大小写res = models.User.objects.filter(name__contains='e')print(res)# 查询出名字里面含有e的数据 忽略大小写res = models.User.objects.filter(name__icontains='e')print(res)# 查询出注册时间是 2020 1月res = models.User.objects.filter(register_time__month=10,register_time__year=2021)print(res)
一对多外键增删改查
#一对多外键增删改查--->和单表的增删改查类似,只是会多加一个外键#增1 直接写实际字段models.Book.objects.create(title='中庸',price=85.2,publish_id=1)models.Book.objects.create(title='安德的游戏',price=85.2,publish_id=2)models.Book.objects.create(title='死者代言人',price=85.2,publish_id=2)2 使用虚拟字段 对象publish_obj = models.Publish.objects.filter(pk=1).first()models.Book.objects.create(title='西游记',price=85,pulish=publish_obj)#删 -->级联删除 和该数据有关的数据都会被删除models.Publish.objects.filter(pk=1).delect()#改1 直接写实际字段models.Book.objects.filter(pk=2).update(publish_id=3)2 使用虚拟字段 对象publish_obj = models.Publish.objects.filter(pk=2).first()models.Book.objects.filter(pk=2).update(publish=publish_obj)
多对多外键增删改查
#给书籍添加作者#增第一种方式book_obj = models.Book.objects.filter(pk=2).first()print(book_obj.authors)#app01.Author.None-->当出现这个None的时候就代表着你已经进入了关系表中book_obj.authors.add(2) #给id为2的书籍绑定一个主键为2的作者book_obj.authors.add(2,3)#支持同时添加多个第二种方式author_obj = models.Author.objects.filter(pk=2).first()author_obj1 = models.Author.objects.filter(pk=3).first()book_obj.authors.add(author_obj)book_obj.authors.add(author_obj,author_obj1)"""add给第三张关系表添加数据括号内既可以传数字也可以传对象 并且都支持多个"""#删book_obj.author.remove(2)book_obj.author.remove(2,3)book_obj.author.remove(author_obj3)book_obj.author.remove(author_obj2,author_obj1)"""remove括号内既可以传数字也可以传对象 并且都支持多个"""#改book_obj.authors.set([1,2]) # 括号内必须给一个可迭代对象book_obj.authors.set([3]) # 括号内必须给一个可迭代对象author_obj = models.Author.objects.filter(pk=2).first()author_obj1 = models.Author.objects.filter(pk=3).first()book_obj.authors.set([author_obj,author_obj1]) # 括号内必须给一个可迭代对象'''修改就相对特殊一点,他需要迭代对象装着,且改完就会改完全,可以想象成全删了再加上新的'''# 清空# 在第三张关系表中清空某个书籍与作者的绑定关系book_obj.authors.clear()"""clear括号内不要加任何参数"""
正反向概念
#正向#反向简单来说 可以把外键字段当正版如果我是从有外键字端的表查,我查你就是正向如果我在没有外键的字段表查你,我查你就是反向book ---> 外键字端在书那(正向)--> publishbook <--- 外键字段在书那(反向) <--- piblish"""正向查询按字段反向查询按表名小写_set..."""
多表查询
子查询(基于对象的跨表查询)
# 1.查询书籍主键为1的出版社book_obj = models.Book.objects.filter(pk=1).first()res = book_obj.publishprint(res.name)# 2.查询书籍主键为2的作者book_obj = models.Book.objects.filter(pk=3).first()res = book_obj.author------>app01.Author.None-->出现None的时候,就代表不止一个数据,这是时候要用all()方法得到对象res = book_obj.author.all()rint(res)# 3.查询作者jason的电话号码author_obj = models.Author.objects.filter(name='jason').first()res = author_obj.authordetailprint(res.phone)# 4.查询出版社是东方出版社出版的书(正反向)#正向publish_obj = models.Publish.objects.filter(name='未来出版社').first()book_obj = models.Book.objects.filter(publish=publish_obj)res = book_obj[0]print(res.title)#反向publish_obj = models.Publish.objects.filter(name='未来出版社').first()book_obj = publish_obj.book_set.all()print(book_obj)# 5.查询作者是jason写过的书#反向author_obj = models.Author.objects.filter(name='jason').first()book_obj = author_obj.book_set.all()print(book_obj)#正向author_obj = models.Author.objects.filter(name='jason').first()book_obj = models.Book.objects.filter(author=author_obj)print(book_obj)# 6.查询手机号是110的作者姓名authordetail_obj = models.AuthorDetail.objects.filter(phone=120).first()print(authordetail_obj)author_obj = models.Author.objects-.filter(authordetail=authordetail_obj).first()print(author_obj.name)#反向authordetail_obj = models.AuthorDetail.objects.filter(phone=120).first()author_obj = authordetail_obj.authorprint(author_obj.name)"""基于对象反向查询的时候当你的查询结果可以有多个的时候 就必须加_set.all()当你的结果只有一个的时候 不需要加_set.all()正向查询也是一样且,正向查询一样可以用对象代替,如果我们不知道对象的主键名,而想用正向时就可以用这个方法直接举个栗子查询作者是jason写过的书先查到作者是jason这个对象 author_obj然后找书,因为书这个表建有书和作者多对多的关系表,所以直接 author=author_obj 就可以查到"""
联表查询(基于双下划线的跨表查询)
#基于双下划线的跨表查询1.查询jason的手机号和作者姓名res = models.Author.objects.filter(name='jason').values('authordetail__phone','name')print(res)#反向res =models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__name')print(res)2.查询书籍主键为3的出版社名称和书的名称res = models.Book.objects.filter(pk=3).values('title','publish__name')print(res)#反向res = models.Publish.objects.filter(book__pk=3).values('name','book__title')print(res)3.查询书籍主键为1的作者姓名res = models.Book.objects.filter(pk=3).values('author__authordetail__phone','author__name')print(res)#反向res = models.Author.objects.filter(book__pk=3).values('authordetail__phone','name')print(res)'''简单描述下双下划线的跨表查询理论上,表与表之间存在联系,就可以通过双下划线查到用法呢也简单依旧是正向查询按字段,反向查询按表名小写比如我要查书籍主键为1的出版社名称和书的名称,那么书籍的名字就是自己表有的,直接输入字段,出版社名称就跨到出版社表去拿 publish__name如果是跨多表查询,建议使用正向,反向查询的话要找中间关系表不然有点麻烦,看第三个题目即可'''
思考题目
今日考题1.什么是FBV与CBV,能不能试着解释一下CBV的运作原理FBV(function base views) 就是在视图里使用函数处理请求。CBV(class base views) 就是在视图里使用类处理请求CBV其实就是FBV 简单来说 CBV要了解三个方法as_view方法:这个方法只要记住这是个类方法用完之后就是返回view方法view方法:简单来说就执行dispatch方法dispatch方法就是根据你前端返回的请求方式,去匹配执行你后端根据不同请求定义的函数方法2.模版语法的传值需要注意什么,常见过滤器及标签有哪些传值记得如果是传函数或者类这些的话,不需要加括号,前端会自动调用常见过滤器:lengthfilesizeformatdateslicetruncatecharstruncatewords...常见标签for循环{% for %}{% endfor %}if判断{% if %}{% elif %}{% endif %}{% empty %}with起别名{% with li.4.1.1.key as key %}<h1>{{ key }}</h1>{% endwith %}3.自定义过滤器,标签,inclusion_tag的流程1.在应用下创建一个名字 必须为 templatetags文件夹2.在该文件夹内创建任意名称的py文件 --->名字随便起3.在py文件内必须有以下两句话(一个字符都不能错)from django import templateregister = template.Library()#自定义过滤器@register.filter(name='filtername')#自定义标签@register.simple_tag(name='tagname')# 自定义inclusion_tag@register.inclusion_tag('渲染的html页面')4.什么是模版的继承与导入,如何正确使用模板的继承意思就是指定一片区域,或者页面,可以直接继承到新页面去,使用去看上一个笔记模板导入:将页面的某一个局部当成模块的形式,哪个地方需要就可以直接导入使用即可
