目录

昨日回顾

视图层
小白必会三板斧 1.JsonResponse
默认只能序列化字典类型
如果你想序列化其他json能够支持的格式
你需要加一个参数safe=False 当你的数据有中文的时候 如果你不想自动转码
你需要制定一个参数 来告诉 你需要动内部任何数据
借助于原生的json模块作为参考依据
json.dumps(obj,ensure_ascii=False)
阅读源码 发现 json_dumps_params = {}
json.dumps(obj,cls,**json_dumps_params) 2.FBV与CBV
FBV
路由
路由与视图函数内存地址
视图
函数 CBV
路由
看似 路由与类点方法
实在还是路由与函数的内存地址
视图

# 只要是处理前端请求的业务逻辑的视图函数 都需要加上request形参
from django.views import View
class MyLogin(View):
def get(self,request):
return render(request,'login.html') def post(self,request):
return HttpResponse('post请求') urs.py
url(r'^login/',views.MyLogin.as_view())
# 1.函数名加括号执行优先级最高
# 2.该方法要么是普通函数 要么是绑定给类的方法
自动变形
url(r'^login/',views.view) # 内部源码
def as_view(cls,**kwargs):
def view(...):
self = cls(...) # 生成自己写的类的对象
return self.dispatch(...) # 一定要确认self到底是谁
# 然后一定要问你一句 对象查找属性和方法的顺序(慢)
return view # 一旦用户敲了login 会自动加括号调用view函数
def dispatch(...)
# 先判断当前请求方式在不在默认的八个请求方法内
if request.method.lower() in self.http_method_allowed:
# 利用发射 获取到方法名对应的属性或者是方法
handler = getattr(self,request.method.lower(),error)
else:
# 提示报错
return handler(...) # 调用请求方法所对应的函数
如何给CBV加装饰器
django推荐你使用内置的模块来给CBV加装饰器
from django.utils.decorators import method_decorator
# 1.直接在类上面装
method_decorator(wrapper,name='给类内部哪个方法装')
# 2.直接在类的内部方法上装
method_decorator(wrapper)
# 3.给类内部所有的方法都装 重写dispacth方法
method_decorator(wrapper) 模板层
1.模板语法的传值
python所有的基本数据类型全部支持 函数
会自动加括号调用 并且函数如果需要参数 那么模板语法不支持 类
会自动加括号实例化 产生对象
# 只要对象能够加括号调用 那么模板语法都会自动加括号
对象
直接传对象 显示的是对象的内容地址 你可以定义__str__来控制对象的展示 对象在html页面上可以调用绑定方法 2.过滤器的使用
语法结构 |
语法特点 会将|左边的数据当做第一个参数传入 :右边的数据当做第二个参数传入 |length
|add
|default:'默认值' # 类似于get方法和getattr方法
|slice:'2:9:2'
|filesizeformat # 将数字格式化成表示容量大小的单位
|truncatechars # 截取字符 包含三个点
|truncatewords # 截取单词 按空格算单词数 不包含三个点
|safe # 告诉浏览器文本内容是安全的 如果有html标签 正常识别渲染即可 前后端取消转义的方法
前端
|safe 后端
from django.utils.safestring import mark_safe
res = mark_safe('<a href='https://www.baidu.com'>点我</a>')
# 也就意味着 html代码可以不再html文件内写
# 可以在后端写html代码 然后传递给前端 3.标签
一对逻辑
if判断 for循环
for循环内部有一个forloop对象
该对象可以判断for循环的开始和结束 first last
也可以帮你获取索引或者数据计数 counter0 counter for循环和if判断嵌套使用
{% for i in l %}
{% if forloop.first %}
第一次操作
{% elif forloop.last %}
最后一次操作
{% else %}
中间操作
{% endif %}
{% empty %}
如果for循环对象是空 执行empty内的逻辑
{% endfor %} with起别名 自定义过滤器 标签 inclusion_tag
1.先在应用下创建一个名字必须交templatetags文件夹
2.文件夹内部创建一个任意名称的py文件(mytag)
3.py文件内必须先写两句代码
from django.template impory Library register = Library() @regiser.filters(name='过滤器的名字')
def index():
pass @register.simple_tag(name='标签名字')
def index1():
... @regisrer.inclusion_tag('html文件名',name='名字')
def index2():
... 如何使用自定义的
{% load 任意名称的py文件名mytag %} 模板的继承
当一个页面需要被频繁使用的时候 你可以考虑使用模板的继承 先通过block块划定后期可能需要修的区域 一个模板上通常一个有三块区域
css
一个
html内容
可以有多个
js 一个 如何使用模板
{% extends '模板的名字' %} {% block css %}
修改模板中css区域内容
{% endblock %} 模板的导入
{% include '你要想导入的html文件名' %}

模型层

1.配置测试脚本

1.1 应用下tests文件

直接在某一应用下的tests文件中书写代码(去manage.py拷贝前四行代码),然后手动写两行代码

import os

if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings") import django
django.setup()
-----------------------以上是配置代码------------------------
# 一定要等待测试脚本搭建完毕之后 才能导入django文件进行测试
from app01 import models
'''测试代码'''

1.2 新建任意名称文件

一样书写以上代码,也可以

2. 数据的增删改查

2.1 创建数据

1.create方法

直接插入数据进行保存

book_obj = models.Books.objects.create(title='挪威的森林',price=123.23,pulish_date='2019-09-09')

book_obj = models.Books.objects.create(title='人间失格',price=222.23,pulish_date=ctime)

print(book_obj)

2.对象的save()方法

利用对象的绑定方法(实例化对象传值,利用对象的save方法创建保存)

book_obj = models.Books(title='我是猫',price=467.78,pulish_date='2019-02-22')
book_obj.save()

queryset对象

filter查询出来的结果是一个Queryset对象

  • 只要是Queryset对象就可以无限制的调用Queryset方法

    res = models.Books.objects.filter(pk=1).filter().filter().filter().filter()
  • 只要是Queryset对象就可以通过.query查看当前结果对应的sql语句

    res.query
    SELECT `app01_books`.`id`, `app01_books`.`title`, `app01_books`.`price`, `app01_books`.`publish_date` FROM `app01_books` WHERE `app01_books`.`id` = 1

2.2 修改数据

pk会自动查找到当前表的主键字段,后期都是使用pk指代主键字段

res = models.Books.objects.filter(pk=1)
print(res) # <QuerySet [<Books: Books object>]>

1.利用Queryset方法update

models.Books.objects.filter(pk=2).update(price=333.33)

2.利用对象 get与filter

使用get与save,该方法不推荐使用

利用对象的修改 内部其实是重头到位将数据的所有字段都重新写一遍

book_obj = models.Books.objects.get(pk=3)
book_obj.price = 888.88
book_obj.save() # 对象的保存

get与filter的区别

  • filter获取到的是一个Queryset对象,类似一个列表
  • get获取到的直接就是数据本身
  • 当条件不存在的情况下
    • filter不会报错直接返回一个空,推荐使用filter方法
    • get则会直接报错

2.3 删除数据

1.利用Queryset方法 delete

models.Books.objects.filter(pk=3).delete()

2.利用对象的delete方法

book_obj = models.Books.objects.get(pk=3)
book_obj.delete()

2.4查询数据 十三门徒

orm语句的查询默认都是惰性查询,只有当你真正要使用到数据的时候才会执行orm语句

    res0 = models.Books.objects.filter(pk=1)
res1 = models.Books.objects
res2 = models.Books
res3 = models print(res0,type(res0))
# <QuerySet [<Books: Books object>]> <class 'django.db.models.query.QuerySet'> print(res1,type(res1))
# app01.Books.objects <class 'django.db.models.manager.Manager'> print(res2,type(res2))
# <class 'app01.models.Books'> <class 'django.db.models.base.ModelBase'> print(res3,type(res3))
# <module 'app01.models' from 'D:\\pycharm\\项目\\开课练习\\day53\\app01\\models.py'> <class 'module'>

自动打印对应sql语句

如果你想查看所有的orm语句内部对应的sql语句,你可以直接在配置文件setting中配置相应的代码即可

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.查询所有 all()

返回Queryset对象

res = models.Books.objects.all()
print(res) # <QuerySet [<Books: Books object>, <Books: Books object>, <Books: Books object>]>

2.筛选 filter()

返回Queryset对象

相当于你原生sql语句里面的where,filter中多个参数之间是and关系

res = models.Books.objects.filter(pk=1)
res = models.Books.objects.filter(pk=1,title='挪威的森林')
print(res)

3.筛选 get()

获取数据对象本身

条件不存在会直接报错,并且查询条件必须唯一, 不推荐使用

    res = models.Books.objects.get(pk=2)
print(res) # Books object

4.取第一个 first()

获取数据对象

取Queryset对象中的第一个数据对象

res = models.Books.objects.filter(title='我是猫').first()
print(res) # Books object
print(res.title) # 我是猫

5.取最后 last()

获取数据对象

取Queryset对象中的最后一个数据对象

res = models.Books.objects.filter(title='我是猫').last()
print(res) # Books object
print(res.id) # 5

6.计数 count()

返回数字

统计数据的个数

res = models.Books.objects.count()
print(res) # 4

7.获取指定字段值 values()

返回Queryset对象,列表套字典形式

获取数据对象中指定的字段的值,可以有多个

    res = models.Books.objects.values('title','price')
print(res)
# <QuerySet [{'title': '挪威的森林', 'price': Decimal('123.23')}, {'title': '人间失格', 'price': Decimal('333.33')}, {'title': '我是猫', 'price': Decimal('888.88')}, {'title': '我是猫', 'price': Decimal('333.77')}]>

8.获取指定字段值 values_list()

返回Queryset对象,列表套元组形式

    res = models.Books.objects.values_list('title')
print(res)
# <QuerySet [('挪威的森林',), ('人间失格',), ('我是猫',), ('我是猫',)]>

9.排序 order_by()

按照指定的字段进行排序,默认是升序,字段前添加-符号降序排列

res = models.Books.objects.order_by('price')

print(res)
# <QuerySet [<Books: Books object>, <Books: Books object>, <Books: Books object>, <Books: Books object>]>

语义明确 使用all().order_by('')

res = models.Books.objects.all().order_by('price')

降序

res = models.Books.objects.order_by('-price')

10.颠倒顺序 reverse()

颠倒的对象必须提前排序,与order_by联用,单独使用没有效果

res = models.Books.objects.all().order_by('price').reverse()

11.排除...之外 exclude()

返回Queryset对象

将拥有某一个字段排除出去

res = models.Books.objects.all().exclude(title='我是猫')
print(res)
# <QuerySet [<Books: Books object>, <Books: Books object>]>

12.判断查询结果是否有值 exists()

返回布尔值

res = models.Books.objects.filter(pk=100).exists()
print(res) # False

13.对查询结果去重 distinct()

去重的前提是,必须完全相同( id不同也不行 ),可以与.values('')配合使用

res = models.Books.objects.values('title')
print(res) # <QuerySet [{'title': '挪威的森林'}, {'title': '人间失格'}, {'title': '我是猫'}, {'title': '我是猫'}]> res = models.Books.objects.values('title').distinct()
print(res) # <QuerySet [{'title': '挪威的森林'}, {'title': '人间失格'}, {'title': '我是猫'}]>

2.5 神奇的双下划线方法

  • __gt 大于
  • __lt 大于
  • __gte 大于等于
  • __lte 小于等于
  • __lt 大于
  • __in=['',''] 取列表内固定参数
  • __range=(,) 取范围内(头尾兼顾)
  • date字段
    • 可以通过在其后加__year,__month,__day等来获取date的特点部分数据,指定获取年月日数据
  • 模糊查询
    • __startswith='' 查询以...开头
    • __endswith='' 查询以...结尾
    • __contains='' 查询中间有某一字符的(默认区分大小写)
      • __icontains=''前面加i不区分大小写

mysql中的模糊查询

关键字like
%:匹配任意个数的任意字符
_:匹配一位任意的字符
models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值

models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(name__contains="ven") # 获取name字段包含"ven"的
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 models.Tb1.objects.filter(id__range=[1, 3]) # id范围是1到3的,等价于SQL的bettwen and 类似的还有:startswith,istartswith, endswith, iendswith  date字段还可以:
models.Class.objects.filter(first_day__year=2017)
date字段可以通过在其后加__year,__month,__day等来获取date的特点部分数据
# date
#
# Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
# Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) # year
#
# Entry.objects.filter(pub_date__year=2005)
# Entry.objects.filter(pub_date__year__gte=2005) # month
#
# Entry.objects.filter(pub_date__month=12)
# Entry.objects.filter(pub_date__month__gte=6) # day
#
# Entry.objects.filter(pub_date__day=3)
# Entry.objects.filter(pub_date__day__gte=3) # week_day
#
# Entry.objects.filter(pub_date__week_day=2)
# Entry.objects.filter(pub_date__week_day__gte=2)
需要注意的是在表示一年的时间的时候,我们通常用52周来表示,因为天数是不确定的,老外就是按周来计算薪资的哦~

3. 多表查询

时间类型

DateField(auto_now_add=True)
时间类型
auto_now:每次修改数据的时候会自动更新数据(只会展示最新的一次修改时间)
auto_now_add:当数据创建出来的时候,会自动将创建时间记录下来,适用于注册

1.表的创建与表关系的建立

from django.db import models

# Create your models here.

# 多表联查

# 书
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_add=True)
# 与出版社表关联 一对一
publish = models.ForeignKey(to='Publish')
# 与作者多对多关系
authors = models.ManyToManyField(to='Author') # 出版社
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64) # 作者
class Author(models.Model):
name = models.CharField(max_length=32)
email = models.EmailField()
# 与作业详情页一对一
author_detail = models.OneToOneField(to='AuthorDetail') # 作者详细
class AuthorDetail(models.Model):
name = models.BigIntegerField()
addr = models.CharField(max_length=64)

2.一对多字段数据的增删改查

2.1 增 create()

1.直接传表字段

传表里的实际字段,跟数据主键值

models.Book.objects.create(title='京华烟云',price=222.22,publish_id=1)

2.直接传对象

传给虚拟字段(外键名的虚拟字段),跟数据对象,(查找想要关联的对象传入)

publish_obj = models.Publish.objects.filter(pk=2).first()

models.Book.objects.create(title='四世同堂',price=333.33,publish=publish_obj)

2.2 改 update()

1.直接传表字段

传表里的实际字段,跟数据主键值

models.Book.objects.filter(pk=1).update(publish_id=3)

2.直接放对象

传虚拟字段,跟数据对象

publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.filter(pk=1).update(publish=publish_obj)

2.3 删 delete()

删除有外键关系的表字段,默认是级联删除.

models.Publish.objects.filter(pk=1).delete()

3.多对多字段的增删改查

3.1 增 add()

add()方法能够向第三张表添加数据,既支持传数字,也支持传对象,两种都可以是多个

1.直接传数字

# 获取主键为2的书籍对象
book_obj = models.Book.objects.filter(pk=2).first()
# 根据对象点第三张表的外键字段进行添加
book_obj.authors.add(1) # 给第三张表里的书籍绑定一个主键为1的作者
book_obj.authors.add(2,3) # 给第三张表里的书籍绑定主键为2和3的作者

2.传对象

# 获取主键为2的书籍对象
book_obj = models.Book.objects.filter(pk=2).first()
# 获得author中主键为1,2的对象
author_obj = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first()
# 书籍对象.authors进入第三张表中添加
book_obj.authors.add(author_obj,author_obj2 )

3.2 改 set(可迭代对象)

set()方法支持传多个,需要使用(可迭代对象)的方式,其原理是先删除再添加.

1.直接传数字

book_obj = models.Book.objects.filter(pk=2).first()

book_obj.authors.set((1,))
book_obj.authors.set((2,3))

2.传对象

# 获取主键为2的书籍对象
book_obj = models.Book.objects.filter(pk=2).first() # 获得author中主键为1,2的对象
author_obj = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first() book_obj.authors.set((author_obj,author_obj2 ))

3.3 删 remove()

数字对象都可以,支持传多个,不需要迭代

1.直接传数字

book_obj = models.Book.objects.filter(pk=2).first()

book_obj.authors.remove(1)
book_obj.authors.remove(2,3)

2.传对象

book_obj = models.Book.objects.filter(pk=2).first()

author_obj = models.Author.objects.filter(pk=1).first()
author_obj2 = models.Author.objects.filter(pk=2).first() book_obj.authors.remove(author_obj)
book_obj.authors.remove(author_obj,author_obj2 )

3.4 清空 clear()

删除某个数据在第三张表中的所有记录

将书籍主键为2的对象,在第三张表中清除掉
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.clear()

4. 跨表查询

正反向查询

1.正向查询按 关系字段

正向查询
具有外键关系字段的一方向无关系的一表的查询是正向

2.反向查询按 表名小写+_set

反向查询
没有外键关系字段的表向有的表查询是反向

1.基于对象的跨表查询

子查询

正向查询

当正向查询
点击外键字段数据有多个的情况下,需要.all()
app01.Author.None 即加.all()

题目

    # 查询书籍主键为2的出版社名称

    book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.publish) #出版社对象
print(book_obj.publish.name) #出版社名称
    # 查询书籍主键为4的作者姓名
book_obj = models.Book.objects.filter(pk=4).first()
print(book_obj.authors) # app01.Author.None
print(book_obj.authors.all()) # 拿到主键为4的作者名列表

反向查询

反向查询时
一对一查询需要 '表名小写'
一对多,多对多查询需要 '表名小写_set.all()`

题目

    # 查询出版社是东方出版社出的书籍
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set.all())
    # 查询作者是jason写的书
author_obj = models.Author.objects.filter(name='Jason').first()
print(author_obj.book_set) # app01.Author.None
print(author_obj.book_set.all()) # 写过的书籍

2.基于双下划线的跨表查询

联表操作

正向查询

写外键字段就相当于已经跨到了字段所关系的表中,你想要改表的哪个字段信息,只需要加__获取即可

题目

# 查询书籍主键为2的出版社名称
res = models.Book.objects.filter(pk=2).values('publish__name')
print(res)
# 查询书籍pk为2的作者姓名和邮箱
res = models.Book.objects.filter(pk=2).values('authors__name','authors__email')
print(res)

反向查询

反向查询  表名小写__字段
filter(表名小写__字段=值)

题目

# 获取书籍主键为2的出版社名称
res = models.Publish.objects.filter(book__pk=2).values('name')
print(res)
# 获取书籍pk为2的作者姓名与邮箱
res = models.Author.objects.filter(book__pk=2).values('name','email')
print(res)

连续跨表

# 获取书籍pk为2的作者的手机号
res = models.Book.objects.filter(pk=2).values('authors__author_detail__phone')

最新文章

  1. 窥探Swift之使用Web浏览器编译Swift代码以及Swift中的泛型
  2. JavaScript异步编程(2)- 先驱者:jsDeferred
  3. C#进阶系列——DDD领域驱动设计初探(三):仓储Repository(下)
  4. sql server 中不同服务器上的数据库中表怎么互导数据
  5. Oracle Partition By 的使用
  6. 初版storm项目全流程自动化测试代码实现
  7. hadoop 流streaming跑python程序
  8. php产生随机数函数
  9. stack UVA 442 Matrix Chain Multiplication
  10. 搭建LAMP
  11. javaweb学习总结(四十四)——监听器(Listener)学习
  12. vijosP1026毒药?解药?
  13. 【HDOJ】3549 Flow Problem
  14. 英语学习APP的案例分析
  15. 了解前端中的SPA
  16. jsp标签jsp:setProperty用法
  17. 关于web-root和web-inf的用处
  18. python冒泡排序法
  19. win7安装Ubuntu变双系统以及删除Ubuntu分区操作
  20. springboot中radis配置和使用【进阶二】

热门文章

  1. 【GStreamer开发】GStreamer基础教程09——收集媒体信息
  2. 洛谷 题解 P1041 【传染病控制】
  3. 软件素材---linux C语言:linux下获取可执行文件的绝对路径--getcwd函数
  4. 题解 Luogu P1110 【[ZJOI2007]报表统计】
  5. Python-05-字符串格式化
  6. QT-入门:创建项目时遇到工程工具集(Kit)找不到问题
  7. NIO堆外内存与零拷贝
  8. Linux权限管理:ACL 权限
  9. js new到底做了什么?如何重写new?(转)
  10. redis哈希表数据类型键的查询和删除命令