Django
第五十二章
内容规格
Python的基础
面向对象
网络
并发
数据库
前端
今日内容
- web框架 原理
- Django的下载安装使用
百度 socket服务端
- socket服务端启动
2. 绑定ip和端口
3. 监听等待连接 - 接受数据
- 返回数据
- 断开连接
浏览器 socket客户端
4. socket客户端启动
- 连接(ip和端口)
- 发送数据
- 接受数据
- 断开连接
https://www.cnblogs.com/maple-shaw/articles/9060408.html
HTTP协议:
http是请求和应答的标准
请求方式:8种 主要是GET POST
状态码 1xx 2xx 3xx 4xx 5xx
请求格式:
‘请求方式 路径 协议版本
请求头: 值
请求头: 值
请求数据’
响应格式:
'协议版本 状态码 状态描述
请求头: 值
请求头: 值
响应数据'
web框架的实现的功能:
- socket收发消息
- 根据不同的路径返回不同的内容
- 返回HTML页面
- 返回动态的页面 (模板的渲染 字符串的替换)
web框架
Django 2 3 4
flask 2 3
tornado 1 2 3 4
Django 大而全
flask tornado 轻量级的框架
Django
下载:
-
命令行
pip install -i django==1.11.25 -i https://pypi.tuna.tsinghua.edu.cn/simple
-
pycharm
在项目的解释器中找对应的Django版本下载
创建项目
-
命令行
django-admin startproject 项目名
-
pycharm
file ——》 new project ——》 填写项目名称 ——》 选择解释器 ——》 create
启动项目
-
命令行
python manage.py runserver # 127.0.0.1:8000
python manage.py runserver 80 # 127.0.0.1:80
python manage.py runserver 0.0.0.0:80 # 0.0.0.0:80
-
pycharm
-
简单使用
-
urls.py中写路径和函数的对应关系
urlpatterns = [ url(r'^index/', index), ] -
写函数
from django.shortcuts import HttpResponse ,render def index(request): # 逻辑 # return HttpResponse('欢迎进入day5项目') # 返回字符串 return render(request,'index.html') # 返回一个HTML页面 页面写在templates文件夹中
作业:
用bootstrap写登录页面,使用Django返回给浏览器
第五十三章
内容回顾
HTTP
规定请求和响应的格式。
请求方法
8种 GET POST ( PUT DELETE HEAD OPTIONS TRACE CONNECT )
状态码
1xx 请求已接受,进一步进行处理
2xx 请求已经接受,也正常处理
3xx 重定向
4xx 请求的错误 403 404
5xx 服务器的错误
URL
https://www.sogou.com/web?query=苍老师&_asf=www.sogou.com
协议 : https
域名: www.sogou.com ip
端口: https (:443) http (:80)
路径: /web
查询的参数: ?后面 k1=v1&k2=v2
请求和响应的格式
请求(浏览器给服务端发的消息) request
‘请求方式 路径 HTTP/1.1
k1:v1
k2:v2
请求数据(请求体)’
响应(服务器返回给浏览器的消息) response
'HTTP/1.1 状态码 状态描述
k1:v1
k2:v2
响应数据(响应体)’'
请求和响应的步骤
- 在浏览器的地址栏种输入URL地址,回车,发个一个GET请求;
- Django接受到请求,根据URL的路径找到对应的函数,执行函数拿到结果
- Django将结果封装成http响应的报文返回浏览器
- 浏览器接受响应,断开连接,解析数据。
框架的功能
- socket收发消息 2. 根据不同路径返回不同的结果(返回HTML页面) 3. 返回动态的页面( 模板的渲染 字符串的替换 )
Django部分
-
下载安装
命令行:
pip install django==1.11.25 -i 源
pycharm:
- 创建项目
命令行:
django-admin startproject 项目名
pycharm
区别: pycharm创建时帮忙创建一个templates的文件夹,配置了模板的路径
-
启动项目
命令行:
cd 项目的根目录下
python manage.py runserver # 127.0.0.1:8000
python manage.py runserver 80 # 127.0.0.1:80
python manage.py runserver 0.0.0.0:80 # 0.0.0.0:80
pycharm:
点绿三角 相关的配置
-
使用:
1. 设计URL 和 函数的对应关系 urls.py urlpatterns = [ url(r'^index/', index), ] 2. 写函数 from django.shortcuts import HttpResponse,render def 函数名(request): # 逻辑 # 查询数据库 插入 # 返回信息给浏览器 return HttpResponse('字符串') return render(request,‘html文件名’)
今日内容
1.静态文件的配置
settings:
STATIC_URL = '/static/' # 静态文件的别名 以它做开头
STATICFILES_DIRS = [ # 静态文件存放的具体路径
os.path.join(BASE_DIR,'static',)
]
2.登录示例
form表单提交数据
action="" 向当前的地址进行提交 method="post" 请求方式 2. input需要有name属性 value值 3. button按钮或者input 类型是submit
在settings中注释一行代码,注释后可以提交post请求
MIDDLEWARE
'django.middleware.csrf.CsrfViewMiddleware'
request.method 请求方式 GET POST
request.POST POST请求的数据 {}
redirect(‘要重定向的地址’) 重定向
3.app
创建app
python manage.py startapp app名称
注册app
INSTALLED_APPS = [
...
'app01',
'app01.apps.App01Config' # 推荐写法
]
app文件目录
admin.py admin管理后台 增删改查数据库
apps.py app相关
models.py 数据库表相关
views.py 写函数(逻辑)
4.ORM
对应关系
类 ——》 表
对象 ——》 数据行(记录)
属性 ——》 字段
django要使用mysql数据库流程
-
创建一个mysql数据库;
-
在settings中配置数据库信息:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 引擎 数据库类型 'NAME': 'day53', # 数据库名称 'HOST': '127.0.0.1', # ip 'PORT': 3306, # 端口 'USER': 'root', # 用户名 'PASSWORD': '123' # 密码 } } -
告诉django使用pymysql模块连接数据库
import pymysql pymysql.install_as_MySQLdb() # 能执行就可以 -
在app下写了model
class User(models.Model): username = models.CharField(max_length=32) # username varchar(32) password = models.CharField(max_length=32) # username varchar(32) -
执行命令 让数据有对应的结构的变化
python manage.py makemigrations # 检查所有已经注册的app下的models.py的变化 记录成一个文件
python manage.py migrate
ORM操作
from app01.models import User
User.objects.all() # 查询所有的数据 QuerySet 对象列表 【 对象 】
User.objects.get(username='alexs',password='alexdsb')
# 对象 get 只能获取数据库唯一存在的数据 有且唯一 (不存在或者多条数据就报错)
User.objects.filter(password='dsb') # 获取满足条件的所有对象 对象列表
第五十四章
内容回顾
- 下载
命令行:
pip install django==1.11.25 -i 源
pycharm:
file _> settings _> 项目 ——》 解释器 ——》 点+号 ——》 输入django ——》 选择版本 ——》 下载
2.创建项目
命令行:
django-admin startproject 项目名
pycharm:
file _> new project ——》 选择django ——》 输入项目的路径 ——》 选择解释器 ——》 templates 还有app名称
3.启动项目
命令行:
切换项目的根目录下 manage.py
python manage.py runserver # 127.0.0.1:8000
python manage.py runserver 80 # 127.0.0.1:80
python manage.py runserver 0.0.0.0:80 # 0.0.0.0:80
pycharm:
找绿三角 点击 (前面是django的项目)
配置ip和端口
4.settings的配置
模板文件 TEMPLATES DIRS [ os.path.join(BASE_DIR,'templates') ]
静态文件
STATIC_URL ='/static/' # 静态文件的别名
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static') ,
os.path.join(BASE_DIR,'static1')
]
数据库配置
APP
中间件
注释一个 csrf 效果: 可以提交post请求
-
APP
创建APP
python manage.py startapp app名称
注册APP
INSTALLED_APPS = [
'app01',
'app01.apps.App01Config' 推荐写法
]
-
urls.py
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.login), url(r'^index/', views.index), ] -
views.py
from django.shortcuts import render,HttpResponse,redirect def login(request): # 逻辑 renturn HttpResponse('xxx')HttpResponse() 返回的字符串
render(request,'模板的文件名') 返回HTML页面
redirect('地址') 重定向
-
get和post
get 获取页面 资源
/sssss/?k1=v1&k2=v2
request.GET {} request.GET.get('key')
post 提交数据
request.POST {} request.POST.get('key')
-
form的表单
- form标签的属性 action='' 提交的地址 method='post' 请求方式 novalidate 不在前端做校验
- input标签要有name属性 value的值
- 有个type=‘submit’ 的input或者button按钮
-
django使用mysql的流程:
-
创建一个mysql数据库
-
在settings中配置数据库的信息
EGNIGE 引擎 mysql
NAME 数据库名称
HOST ip
PORT 端口 3306
USER 用户名
PASSWORD 密码
-
告诉使用pymysql替换mysqldb的模块
写在与settings同级目录下的
__init__中:import pymysql pymysql.install_as_MySQLdb() -
在已经注册的app下的models.py中写类(继承models.Model)
class User(models.Model): username = models.CharField(max_length=32) # username varchar(32) -
执行命令
python manage.py makemigrations # 记录了一个models的变更记录 python manage.py migrate # 将models的变更记录同步到数据库中
-
-
ORM
对象关系映射
对应关系
类 —— 》 表
对象 ——》 数据行(记录)
属性 ——》 字段
ORM能做的事情:
-
对数据库中表操作
-
对表中的数据操作
orm具体的操作:
from app01.models import User User.objects.all() # 获取到所有的数据 QuerySet [User对象] 对象列表 User.objects.get() # 获取一个对象 只能获取唯一存在的对象 如果不存在或者是多个结果就报错 User.objects.filter() # 获取到所有满足条件的对象 QuerySet [User对象] 对象列表
今日内容
图书管理系统
出版社 书籍 作者
出版社的管理
展示
-
设计URL地址
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publisher_list/', views.publisher_list), ] -
写函数
def publisher_list(request): # 从数据库中获取所有的出版社的信息 all_publisher = models.Publisher.objects.all() # 对象列表 # 将数据展示到页面中 return render(request,'publisher_list.html',{'k1':all_publisher}) -
模板语法
{{ 变量 }} for循环 {% for i in 变量 %} 循环体 {{ i }} {% endfor %}
新增
方式一:
models.Publisher.objects.create(name=pub_name,addr=pub_addr) # 对象
方式二:
pub_obj = models.Publisher(name=pub_name,addr=pub_addr) # 内存中的对象 和数据库没关系
pub_obj.save() # 插入到数据库中
删除
models.Publisher.objects.filter(pid=pid).delete() # 对象列表 删除
models.Publisher.objects.get(pid=pid).delete() # 对象 删除
编辑
pub_obj.name = pub_name
pub_obj.addr = pub_addr
pub_obj.save() # 将修改提交的数据库
第五十五章
内容回顾
1.django中所有的命令
-
下载django
pip install django==1.11.25 -i 源
-
创建django项目
django-admin startproject 项目名
-
启动项目
切换到项目目录下
python manage.py runserver # 127.0.0.1:8000
python manage.py runserver 80 # 127.0.0.1:80
python manage.py runserver 0.0.0.0::80 # 0.0.0.0::80
-
创建app
python manage.py startapp app名称
-
数据库迁移的命令
python manage.py makemigrations # 检测已经注册app下的models变更记录
python manage.py migrate # 将变更记录同步到数据库中
2.django的配置
-
静态文件
STATIC_URL = '/static/' # 静态文件的别名
STATICFILES_DIRS = [ # 静态文件存放的路径
os.path.join(BASE_DIR ,'static')
]
-
数据库
ENGINE mysql
NAME 数据库名称
HOST ip
PORT 端口号
USER 用户名
PASSWORD 密码
-
中间件
注释掉 一个 csrf (可以提交POST请求)
-
app
INSTALLED_APPS = [
'app名称'
‘app名称.apps.app名称Config’
]
-
模板
TEMPLATES DIRS =[ os.path.join(BASE_DIR ,'templates')]
3.django使用mysql数据库的流程
-
创建一个mysql数据库
-
配置数据库连接信息
ENGINE mysql
NAME 数据库名称
HOST ip
PORT 端口号
USER 用户名
PASSWORD 密码
-
告诉django使用pymysql替换Mysqldb
在与settings同级目录下的init文件中写:
import pymysql pymysql.install_as_MySQLdb() -
在models中写类(继承models.Model)
class Publisher(models.MOdel): pid = models.AutoField(primry_key=True) name = models.CharField(max_length=32,unique=True) -
执行数据库迁移的命令
python manage.py makemigrations # 检测已经注册app下的models变更记录
python manage.py migrate # 将变更记录同步到数据库中
4.get和post的区别
发送get的方式:
- 地址栏中输入地址 回车
- a 标签
- from表单
?k1=v1&k2=v2 request.GET.get(key) # url携带的参数
发送post请求:
form表单 method ='post'
form表单
1. action='' 向当前地址进行提交 method ='post'
- 所有的input需要有name属性 value
- 需要有button或者一个type=‘submit’的input框
request.POST.get(key)
5.ORM
对象关系映射
对应关系
类 ——》 表
对象 ——》 数据行(记录)
属性 ——》 字段
ORM操作
查询
from app01 import models
models.Publisher.objects.all() # 查询所有的数据 QuerySet 【对象】 对象列表
models.Publisher.objects.get(name='xxx') # 查询有且唯一的对象 没有或者是多个就报错
models.Publisher.objects.filter(name='xxx') # 查询所有符合条件的对象 QuerySet 【对象】 对象列表
for i in models.Publisher.objects.all() :
print(i) # Publisher object __str__()
print(i.name)
新增
models.Publisher.objects.create(name='xxxx',addr='xxxx')
obj = models.Publisher(name='xxxx',addr='xxxx')
obj.save()
删除
models.Publisher.objects.filter(pid=pid).delete()
models.Publisher.objects.get(pip=pid).delete()
编辑
pub_obj.name = 'xxxx'
pub_obj.addr = 'xxxx'
pub_obj.save()
6.模板语法
render(request,‘模板的文件名’,{ key:value })
{{ key }} ——》 value的值
for循环
{% for i in list %}
{{ forloop.counter }}
{{ i }}
{% endfor %}
今日内容
书籍的管理
外键 描述一对多的关系
class Book(models.Model):
title = models.CharField(max_length=32, unique=True)
pub = models.ForeignKey('Publisher',on_delete=models.CASCADE)
on_delete在2.0版本中是必填的
on_delete=models.CASCADE(级联删除)
models.SET()
models.SET_DEFAULT default=值
models.SET_NULL null=True
models.DO_NOTHING
展示
all_books = models.Book.objects.all() # 对象列表
for book in all_books:
print(book)
print(book.title,type(book.title))
print(book.pub) # 外键关联的对象
print(book.pub_id) # 关联对象的id 直接从数据库查询
新增
models.Book.objects.create(title=book_name,pub=models.Publisher.objects.get(pk=pub_id))
models.Book.objects.create(title=book_name,pub_id=pub_id)
模板语法
{% if 条件 %}
满足条件显示的值
{% endif %}
{% if 条件 %}
满足条件显示的值
{% else %}
不满足条件显示的值
{% endif %}
{% if 条件 %}
满足条件显示的值
{% elif 条件1 %}
满足条件显示的值
{% else %}
不满足条件显示的值
{% endif %}
第五十六章
内容回顾
1.django处理请求的流程:
- 在地址栏中输入地址,回车发送一个请求;
- wsgi服务器接收到http请求,封装request对象;
- django根据请求的地址找到对应的函数,执行;
- 函数执行的结果,django将结果封装成http响应的格式返回给浏览器。
2.发请求的途径
1. 地址栏中输入地址 回车 GET请求
2. a标签 GET请求
3. form表单 GET/POST
3.get和post的区别
get 获取页面
?k1=v1&k1=v2 request.GET.get() url 上携带的参数
get请求没有请求体
post 提交数据
提交的数据 在请求体中
4.函数
def func(request):
# 逻辑
return HttpResponse对象
request.GET url上携带的参数 {}
request.POST POST请求提交的数据 {}
request.method 请求方法 GET POST
HttpResponse('字符串') 返回字符串
render(request,'模板文件的名字',{k1:v1}) 返回一个HTML页面
redirect('重定向的地址') 重定向
5.外键
描述 一对多
class Publisher(models.Model):
name = models.CharField(max_length=32)
class Book(models.Model):
title = models.CharField(max_length=32)
pub = models.ForeignKey('Publisher',on_delete=models.CASCADE) # pub_id
展示
from app01 import models
all_books = models.Book.objects.all()
for book in all_books:
print(book.id) print(book.pk)
print(book) # 对象 __str__
print(book.title)
print(book.pub) # 外键关联的对象 print(book.pub.pk) print(book.pub.name)
print(book.pub_id) # 外键关联的对象id
新增
models.Book.objects.create(title='xxxx',pub=关联的对象)
models.Book.objects.create(title='xxxx',pub_id=id)
obj =models.Book(title='xxxx',pub=关联的对象)
obj.save()
删除
models.Book.objects.filter(id=id).delete()
models.Book.objects.filter(id=id).first().delete()
编辑
obj = models.Book.objects.filter(id=id).first()
obj.title = 'xxxxx'
# obj.pub = pub_obj
obj.pub_id = pub_obj.id
obj.save()
6.模板的语法
{{ 变量 }}
for循环
{% for i in list %}
{{ forloop.counter }}
{{ i }}
{% endfor %}
{% if 条件 %}
内容
{% endif %}
{% if 条件 %}
内容
{% else %}
内容2
{% endif %}
{% if 条件 %}
内容
{% elif 条件1 %}
内容
{% else %}
内容2
{% endif %}
今日内容
作者的管理
作者 书籍 多对多的关系
class Author(models.Model):
name = models.CharField(max_length=32)
books = models.ManyToManyField('Book') # 不会生成字段 生成第三张表
展示
all_authors = models.Author.objects.all()
for author in all_authors:
print(author)
print(author.name)
print(author.books,type(author.books)) # 多对多的关系管理对象
print(author.books.all(),type(author.books.all())) # 关系对象列表
all_books = models.Book.objects.all()
for book in all_books:
book # 书籍对象
book.title
book.author_set # 多对多的关系管理对象
book.author_set.all() # 书籍关联的所有的作者对象 对象列表
新增
author_obj = models.Author.objects.create(name=author_name) # 插入作者信息
author_obj.books.set(book_id) # 设置作者和书籍的多对多的关系
多对多关系表的创建方式:
-
django自己创建
class Book(models.Model): title = models.CharField(max_length=32, unique=True) pub = models.ForeignKey('Publisher', on_delete=models.CASCADE) class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField('Book') # 不会生成字段 生成第三张表 -
自己手动创建
class Book(models.Model): title = models.CharField(max_length=32, unique=True) class Author(models.Model): name = models.CharField(max_length=32) class AuthorBook(models.Model): book = models.ForeignKey('Book',on_delete=models.CASCADE) author = models.ForeignKey('Author',on_delete=models.CASCADE) date = models.CharField(max_length=32) -
半自动创建(自己手动创建表 + ManyToManyField 可以利用查询方法 不能用set)
class Book(models.Model): title = models.CharField(max_length=32, unique=True) class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField('Book',through='AuthorBook') # 只用django提供的查询方法 不用创建表 用用户创建的表AuthorBook class AuthorBook(models.Model): book = models.ForeignKey('Book',on_delete=models.CASCADE) author = models.ForeignKey('Author',on_delete=models.CASCADE) date = models.CharField(max_length=32)class Book(models.Model): title = models.CharField(max_length=32, unique=True) class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField('Book',through='AuthorBook',through_fields=['author','book']) # 只用django提供的查询方法 不用创建表 用用户创建的表AuthorBook class AuthorBook(models.Model): book = models.ForeignKey('Book',on_delete=models.CASCADE,null=True) author = models.ForeignKey('Author',on_delete=models.CASCADE,related_name='x1',null=True) tuiianren = models.ForeignKey('Author',on_delete=models.CASCADE,related_name='x2',null=True) date = models.CharField(max_length=32)
周末
学员管理系统
学生表 班级表 教师表
第五十七章
内容回顾
1.django的命令
-
下载
pip install django==1.11.25 -i 源
- 创建项目
django-admin startproject 项目名
-
启动项目
cd 项目的根目录
python manage.py runserver # 127.0.0.1:8000
python manage.py runserver 80 # 127.0.0.1:80
python manage.py runserver 0.0.0.0:80 # 0.0.0.0:80
-
创建APP
python manage.py startapp app名称
-
数据库迁移的命令
python manage.py makemigrations # 检查已经注册的APP下的models.py的变更记录
python manage.py migrate # 将变更记同步到数据库中
2.django的配置
TEMPLATES 模板 DIRS [ os.path.join(BASE_DIR,'templates') ]
静态文件
STATIC_URL = '/static/' # 静态文件的别名
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static')
]
注册的app
INSTALLED_APPS = [
'app01'
'app01.apps.App01Config'
]
中间件
注释掉csrf中间件 可以提交POST请求
数据库的配置
ENGINE : mysql
NAME: 数据库的名称
HOST: ip
PORT : 3306
USER : 用户名
PASSWORD : 密码
3.django使用mysql数据库的流程
-
创建一个mysql数据库
-
数据库settings中的配置
ENGINE : mysql
NAME: 数据库的名称
HOST: ip
PORT : 3306
USER : 用户名
PASSWORD : 密码
-
告诉django使用pymysql连接数据库
写在与settingst同级目录下的
__init__.py中:import pymysql
pymysql.install_as_MySQLdb()
- 在models写类(继承models.Model):
class Publisher(models.Model): pid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) # varchar(32) class Book(models.Model): title = models.CharField(max_length=32) # varchar(32) pub = models.ForeignKey('Publisher',on_delete=models.CASCADE) class Author(models.Model): name = models.CharField(max_length=32) # varchar(32) books = models.ManyToManyField(Book) # 生成第三张表 不会在Author表中生成字段- 执行数据库迁移的命令
python manage.py makemigrations # 检查已经注册的APP下的models.py的变更记录
python manage.py migrate # 将变更记同步到数据库中
4.request 请求相关的内容
request.GET url上携带的参数 {} get()
request.POST POST请求提交的数据 {} get() getlist()
request.method 请求方法 GET POST
5.响应
HttpResponse(‘字符串’) 返回的字符串‘
render(request,'模板的文件名',{}) 返回的是 完整的页面
redirect(重定向的地址 ) 重定向
6.ORM
对象关系映射
对应关系:
类 ——》 表
对象 ——》 数据行(记录)
属性 ——》 字段
具体的操作:
查询
from app01 import models
models.Publisher.objects.all() # 查询所有的数据 QuerySet 对象列表
models.Publisher.objects.get(name='xxx') # 查询满足条件的一条数据(唯一存在) 对象 不存在或者多个就报错
ret = models.Publisher.objects.filter(name='xxx') # 查询满足条件所有的数据 对象列表
ret[0]
ret.first() # 获取第一个对象 取不到就是None
for i in pubs:
i.name
i.pid i.pk
book_obj.title
book_obj.pub # 外键关联的对象
book_obj.pub_id # 外键关联对象的id
author_obj.name
author_obj.books # 关系管理对象
author_obj.books.all() # 所关联的所有的对象 [book,book]
新增
ret = models.Publisher.objects.create(name='xxxx') # 新增数据 返回一个对象
obj = models.Publisher(name='xxxx')
obj.save()
models.Book.objects.create(title='xxxx',pub=出版社对象)
models.Book.objects.create(title='xxxx',pub_id=出版社对象id)
obj = models.Author.objects.create(name='xxx')
obj.books.set([book的id])
删除
models.Publisher.objects.filter(pk=pk).delete()
book_obj.delete()
编辑
book_obj.title = 'xxxx'
book_obj.pub_id =id
book_obj.save()
author_obj.name='xxx'
author_obj.save()
author_obj.books.set([book的id,book的id,book的id])
7.模板
render(request,'模板的文件名',{k1:v1})
变量
{{ k1 }}
for循环
{% for i in list %}
{{ forloop.counter }}
{{ i }}
{% endfor %}
if判读
{% if 条件 %}
满足条件后的结果
{% endif %}
{% if 条件 %}
满足条件后的结果
{% else %}
不满足条件后的结果
{% endif %}
{% if 条件 %}
满足条件后的结果
{% elif 条件1 %}
满足条件后的结果
{% else %}
不满足条件后的结果
{% endif %}
内容回顾
1.MVC和MTV
MVC
M: model 模型 数据库交互
V:view 视图 展示给用户看的 HTML
C :controller 控制器 业务逻辑 传递指令
MTV:
M: model 模型 ORM
T: template 模板
V: view 视图 业务逻辑
2.变量
1.点的使用
{{ 变量 }}
.索引 . key .属性 .方法
优先级:
key > 属性或者方法 > 数字索引
过滤器
{{ value|filter_name }}
{{ value|filter_name:参数 }}
内置的过滤器
https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#built-in-filter-reference
default
{{ 变量|default:'默认值' }} 变量不存在或者为空 显示默认值
filesizeformat
显示文件大小
add
{{ 2|add:'2' }} 数字加法
{{ 'a'|add:'b' }} 字符串的拼接
{{ [1,2]|add:[3,4] }} 列表的拼接
length
返回变量的长度
slice
切片
{{ string|slice:'-1::-1' }}
date 日期格式化
{{ now|date:'Y-m-d H:i:s' }}
safe
{{ a|safe }} 告诉django不需要进行转义
自定义过滤器
-
在app下创建一个名叫templatetags的python包 (templatetags名字不能改)
-
在包内创建py文件 (文件名可自定义 my_tags.py)
-
在python文件中写代码:
from django import template register = template.Library() # register名字不能错 -
写上一个函数 + 加装饰器
@register.filter def str_upper(value,arg): # 最多两个参数 ret = value+arg return ret.upper()
使用:
在模板中
{% load my_tags %}
{{ 'alex'|str_upper:'dsb' }}
第五十八章
内容回顾
1.MVC和MTV
MVC:
M: model 模型 和数据库交互
V: view 视图 展示数据 HTML
C: controller 控制器 业务流程 传递指令
MTV:
M: model 模型 ORM
T:template 模板 HTML
V : view 视图 业务逻辑
2.模板
变量
render(request,‘模板的文件名’,{ k1:v1 })
{{ 变量 }}
{{ 变量.0 }}
{{ 变量.key }}
{{ 变量.keys }} {{ 变量.values }} {{ 变量.items }}
{{ 变量.属性 }} {{ 变量.方法 }}
优先级:
字典的key > 方法或者属性 > 数字索引
过滤器
修改变量的显示结果
语法:
{{ 变量|filter_name }} {{ 变量|filter_name:参数 }}
内置的过滤器
default 变量不存在或者为空的时候使用默认值 {{ 变量|default :‘默认值’ }}
add + 数字的加法 字符串和列表的拼接
length 返回变量的长度
filesizeformat 文件大小格式化 byte PB
upper lower join
slice 切片 {{ list|slice:'1:2:2' } }
date 日期时间格式化 {{ 日期时间类型|date:'Y-m-d H:i:s' }} datetime: Y-m-d H:M:S
settings:
USE_L10N = False
DATETIME_FORMAT = 'Y-m-d H:i:s'
DATE_FORMAT = 'Y-m-d'
safe 前面的内容不用转义 在模板中使用
from django.utils.safestring import mark_safe # py文件中用
自定义过滤器
-
在app下创建一个名为templatetags的python包;
-
在包内创建py文件 (任意指定,my_tags.py)
- 在py文件中写代码
from django import template register = template.Library() # register名字不能错- 写函数 + 加装饰器
@register.filter def str_upper(value,arg): return ''
使用:
模板中使用:
{% load my_tags %}
{{ 变量|str_upper:‘参数’ }}
今日内容
for
{% for i in list %}
{{ forloop.counter }}
{{ i }}
{% endfor %}
{{ forloop.counter }} 循环的索引 从1开始
{{ forloop.counter0 }} 循环的索引 从0开始
{{ forloop.revcounter }} 循环的索引(倒叙) 到1结束
{{ forloop.revcounter0 }} 循环的索引(倒叙) 到0结束
{{ forloop.first }} 判断是否是第一次循环 是TRUE
{{ forloop.last }} 判断是否是最后一次循环 是TRUE
{{ forloop.parentloop }} 当前循环的外层循环的相关参数
{% for tr in table %}
<tr>
{% for td in tr %}
<td > {{ td }} </td>
{% endfor %}
</tr>
{% empty %}
<tr> <td colspan="4" >没有数据</td> </tr>
{% endfor %}
if
{% if alex.age == 84 %}
当前已经到了第二个坎了
{% elif alex.age == 73 %}
当前已经到了第一个坎了
{% else %}
不在坎上,就在去坎上的路上
{% endif %}
注意:
1. 不支持算数运算 + - * / %
2. 不支持连续判断 10 > 5 > 1 false
with
{% with p_list.0.name as alex_name %}
{{ alex_name }}
{{ alex_name }}
{{ alex_name }}
{{ alex_name }}
{% endwith %}
{% with alex_name=p_list.0.name %}
{{ alex_name }}
{{ alex_name }}
{{ alex_name }}
{{ alex_name }}
{% endwith %}
csrf 跨站请求伪造
{% csrf_token %} form表单中有一个隐藏的input标签 name='csrfmiddlewaretoken' value 随机字符串
可以提交post请求
母版和继承
母版:
1. 就是一个HTML页面,提取到多个页面的公共部分;
2. 定义block块,留下位置,让子页面进行填充
继承:
1. 写{% extends ‘母版的名字’ %}
2. 重写block块
注意点:
1. {% extends 'base.html' %} 母版的名字有引号的 不带引号会当做变量
- {% extends 'base.html' %} 上不要写内容,想显示的内容要写在block块中
- 多定义点block块,有css js
组件
一小段HTML代码 ——》 nav.html
{% include 'nav.html' %}
静态文件
{% load static %}
{% static '相对路径' %}
{% get_static_prefix %} 获取静态文件的别名
simple_tag 和 inclusion_tag
自定义simple_tag:
-
在app下创建一个名为templatetags的python包;
-
在包内创建py文件 (任意指定,my_tags.py)
-
在py文件中写代码
from django import template register = template.Library() # register名字不能错 -
写函数 + 加装饰器
@register.simple_tag def str_join(*args, **kwargs): return '*'.join(args) + '_'.join(kwargs.values()) @register.inclusion_tag('page.html') def page(num): return {'num':range(1,num+1)} # 在templates写page.html
使用:
模板中使用:
{% load my_tags %}
{{ 变量|str_upper:‘参数’ }}
{% str_join '1' '2' '3' k1='4' k2='5' %}
{% page 10 %}
第五十九章
内容回顾
模板
变量
{{ 变量 }}
.key .属性 .方法 .索引
过滤器
{{ 变量|过滤器 }} {{ 变量|过滤器:参数 }}
default add filesizeformart date safe join truncatechars
for 循环
{% for i in list %}
{{ i }} {{ forloop }}
{% endfor %}
forloop .counter 当前循环的序号 从1开始
forloop .counter0 当前循环的序号 从0开始
forloop .revcounter 当前循环的序号 到1结束
forloop .revcounter0 当前循环的序号 到0结束
forloop .first 当前循环是否是第一次循环 布尔值
forloop . last 当前循环是否是最后一次循环 布尔值
forloop .parentloop 当前循环的外层循环的参数
for ... empty
{% for i in list %}
{{ i }} {{ forloop }}
{% empty %}
list 为空的时候
{% endfor %}
if判断
{% if 条件 %}
显示的内容
{% endif %}
{% if 条件 %}
显示的内容
{% elif 条件1 %}
显示的内容
{% endif %}
{% if 条件 %}
显示的内容
{% elif 条件1 %}
显示的内容
{% else%}
显示的内容
{% endif %}
if 要注意的内容:
1. 不支持算数运算 (过滤器)
2. 不支持连续判断 (10>5>1)
with
{% with alex.name as alex_name %}
{{ alex_name }}
{% endwith %}
{% with alex_name=alex.name %}
{{ alex_name }}
{% endwith %}
csrf_token
{% csrf_token %}写在form标签内,form标签有一个隐藏的input标签,name=‘csrfmiddlewaretoken’
母版和继承
母版:
本身就是一个HTML页面,提取到多个页面的公共部分,页面中定义多block块。
子页面继承:
1. {% extends ‘母版文件名’ %}
2. 重写block块
注意点:
1. {% extends ‘母版文件名’ %} 文件名带引号 不带引号当做变量
2. {% extends ‘母版文件名’ %} 上面不要写内容 想要显示的内容写在block块中
3. 母版中多定义写block块 css js
组件
一小段HTML代码段 ——》 HTML文件中
{% include 'nav.html' %}
静态文件
{% load static %}
{% static '相对路径' %}
{% get_static_prefix %} STATIC_URL
模板自定义方法
filter simple_tag inclusion_tag
定义:
-
在已注册的app下创建templatetags的python包;
-
在包中创建py文件 (文件名任意指定 my_tags.py)
-
在py文件中写固定的代码:
from django import template register = template.Library() # register的名字也不能错- 写函数 + 加装饰器
# filter @register.filter def str_upper(value,arg) return 'xxxxx' #simple_tag @register.simple_tag def str_join(*args,**kwargs): return 'xxxxx' #inclusion_tag @register.inclusion_tag('li.html') def show_li(num,*args,**kwargs): return {'num':range(1,num+1)} # li.html <ul> {% for i in num %} <li>{{ i }}</li> {% endfor %} </ul>
使用:
{% load my_tags %}
{{ 'xxx'|str_upper:'参数' }}
{% str_join 1 2 3 k1=4 k2=5 %}
{% show_li 3 %}
'
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
'
今日内容
视图
MVC MTV
FBV 和 CBV
FBV function based view
CBV class based view
定义CBV
from django.views import View
class PublisherAdd(View):
def get(self,request):
# 处理get请求的逻辑
return response
def post(self,request):
# 处理post请求的逻辑
return response
写对应关系
url(r'^publisher_add/', views.PublisherAdd.as_view()),
as_view的流程
-
程序加载时,执行View中as_view的方法 ,返回一个view函数。
-
请求到来的时候执行view函数:
-
实例化类 ——》 self
-
self.request = request
-
执行self.dispatch(request, *args, **kwargs)
-
判断请求方式是否被允许:
-
允许
通过反射获取当前对象中的请求方式所对应的方法
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
-
不允许
handler = self.http_method_not_allowed
- 执行handler 获取到结果,最终返回给django
-
-
-
装饰器补充
from functools import wraps
def wrapper(func):
@wraps(func)
def inner(*args, **kwargs):
# 之前
ret = func(*args, **kwargs)
# 之后
return ret
return inner
django中给视图加装饰器
FBV 直接给函数添加装饰器
CBV
from django.utils.decorators import method_decorator
-
加在方法上
@method_decorator(wrapper) def get(self,request): -
加在dispatch方法上
@method_decorator(wrapper) def dispatch(self, request, *args, **kwargs): ret = super().dispatch(request, *args, **kwargs) return ret @method_decorator(wrapper, name='dispatch') class PublisherAdd(View): -
加在类上
@method_decorator(wrapper, name='post') @method_decorator(wrapper, name='get') class PublisherAdd(View):
request
request.method # 请求方式
request.GET # URL上携带的参数
request.POST # POST请求提交的数据 enctype="application/x-www-form-urlencoded"
request.FILES # 上传的文件 enctype="multipart/form-data"
request.path_info # 路径信息 不包含IP和端口 也不包含查询参数
request.body # 请求体 原始数据
request.COOKIES # cookies
request.session # session
request.META # 请求头的信息
request.get_full_path() # 路径信息 不包含IP和端口 包含查询参数
request.is_ajax() # 是否是ajax请求 布尔值
response
HttpResponse('字符串') # 返回字符串
render(request,'模板的文件名',{}) # 返回一个页面
redirect(地址) # 重定向 响应头 Location: 地址
第六十章
内容回顾
视图
FBV CBV
定义CBV
from django.views import View
class PUblisherAdd(View):
# http_method_names = ['get',]
def get(self,request,*args,**kwargs):
# 处理GET请求的具体的逻辑
self.request
return response
def post(self,request,*args,**kwargs):
# 处理GET请求的具体的逻辑
return response
ulrs.py中写对应关系
url(r'add_publisher/',views.PublisherAdd.as_view())
as_view的流程
-
程序启动的时候,类.as_view()方法要执行 ——》 view函数
-
请求到来的时候要执行view函数
-
实例化类 成对象 ——》 self
-
self.request = request
-
执行dispatch的方法
-
判断请求方式是否被允许; http_method_names = []
-
允许
通过反射获取对应请求方式所对应的方法 ——》 handler
-
不允许
http_methid_not_allowed ——》 handler
-
-
执行handler 返回它的执行结果
-
-
加装饰器的方法
form functools import wraps
def timer(func):
@wraps(func)
def inner(*args,**kwargs):
# 之前的操作
ret = func(*args,**kwargs)
# 之后的操作
return ret
return inner
FBV 直接加
CBV
from django.utils.decorators import method_decorator
1. 加在方法上
@method_decorator(timer)
def get(....)
2. 加在类上
@method_decorator(timer,name='get')
class PUblisherAdd(View):
3. 加在dispatch方法上
@method_decorator(wrapper)
def dispatch(self, request, *args, **kwargs):
ret = super().dispatch(request, *args, **kwargs)
return ret
@method_decorator(timer,name='dispatch')
class PUblisherAdd(View):
request对象
request.GET # url上携带的参数 {}
request.POST # POST请求提交的数据 编码类型urlencode
request.method # 请求方式 POST GET
request.FILES # 上传的文件
1. enctype="multipart/form-data"
2. input type = 'file' name='f1'
request.path_info # 路径信息 不包含ip和端口 也不包含查询的参数
request.body # 请求体 浏览器提交的原始数据
request.META # 请求头的信息 小写 ——》 大写 - ——》 _ HTTP_
request.COOKIES # COOKIE
request.session # session
request.get_full_path() # 完整的路径信息 不包含ip和端口 包含查询的参数
request.is_ajax() # 是否是ajax请求
response对象
HttpRsponse('字符串') # 返回字符串 Content-Type: text/html; charset=utf-8
render(request,'模板的文件名',{}) # 返回一个HTML页面
redirect(地址) # 重定向到地址 本质:响应头 Location:地址
JsonResponse({}) # 返回json数据 返回非字典类型safe=False Content-Type: application/json
路由
URLconf
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^blog/$', views.blogs), # /blog/
url(r'^blog/[0-9]{4}/\d{2}/$', views.blog), # /blog/2019/10/
]
url(正则表达式的字符串, 视图函数,)
正则表达式
r'' ^ 开通 $ 结尾 [0-9a-zA-Z]{4} \d \w . ? 0个或1个 *0个或无数个 + 至少一个
分组
urlpatterns = [
url(r'^blog/([0-9]{4})/(\d{2})/$', views.blog),
]
从URL上捕获参数,将参数按照位置传参传递给视图函数。
命名分组
urlpatterns = [
url(r'^blog/(?P<year>[0-9]{4})/(?<month>\d{2})/$', views.blog),
]
从URL上捕获参数,将参数按照关键字传参传递给视图函数。
include
from django.conf.urls import url, include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/', include('app01.urls')),
url(r'^app02/', include('app02.urls')),
url(r'^file_upload/', views.file_upload),
url(r'^get_data/', views.get_data),
]
app01 urls,py
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^publisher_list/', views.publisher_list),
# url(r'^publisher_add/', views.publisher_add),
url(r'^publisher_add/', views.PublisherAdd.as_view()),
# url(r'^publisher_add/', view),
url(r'^publisher_del/(\d+)/', views.publisher_del),
url(r'^publisher_edit/', views.publisher_edit),
]
URL的命名和反向解析
静态路由
URL的命名
url(r'^publisher_list/', views.publisher_list, name='publisher_list'),
URL反向解析
模板
{% url 'publisher_list' %} ——》 解析生成完整的URL路径 '/app01/publisher_list/'
py文件
from django.shortcuts import render, redirect, HttpResponse, reverse
from django.urls import reverse
reverse('publisher_list') ——》 '/app01/publisher_list/'
分组
URL的命名
url(r'^publisher_del/(\d+)/', views.publisher_del,name='publisher_del'),
URL反向解析
模板
{% url 'publisher_del' i.pk %} ——》 解析生成完整的URL路径 '/app01/publisher_del/1/'
py文件
from django.shortcuts import render, redirect, HttpResponse, reverse
from django.urls import reverse
reverse('pub_del',args=(1,)) ——》 '/app01/publisher_del/1/'
命名分组
URL的命名
url(r'^publisher_del/(\d+)/', views.publisher_del,name='publisher_del'),
URL反向解析
模板
{% url 'publisher_del' 1 %} ——》 解析生成完整的URL路径 '/app01/publisher_del/1/'
{% url 'publisher_del' pk=1 %} ——》 解析生成完整的URL路径 '/app01/publisher_del/1/'
py文件
from django.shortcuts import render, redirect, HttpResponse, reverse
from django.urls import reverse
reverse('pub_del',args=(1,)) ——》 '/app01/publisher_del/1/'
reverse('pub_del',kwargs={'pk':1}) ——》 '/app01/publisher_del/1/'
namespace
urlpatterns = [
url(r'^app01/', include('app01.urls', namespace='app01')), # home name=home
url(r'^app02/', include('app02.urls', namespace='app02')), # home name=home
]
反向解析生成URL
{% url 'namespace:name' % }
reverse( 'namespace:name' )
第六十一章
内容回顾
路由系统
urlconf
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^publisher_list/', views.publisher_list, name='publisher_list'),
# url(r'^publisher_add/', views.publisher_add),
]
正则表达式
从上到下进行匹配,匹配到一个就不再往下匹配
r $ ^ \d \w [a-z] [azs]{4} . ? + *
分组和命名分组
url(r'^(publisher)_list/', views.publisher_list, name='publisher_list'),
从URL地址上捕获的参数会按照 位置参数 传递给视图函数
url(r'^(?P<xxx>publisher)_list/', views.publisher_list, name='publisher_list'),
从URL地址上捕获的参数会按照 关键字参数 传递给视图函数
include 路由分发
from django.conf.urls import url, include
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01', include('app01.urls')),
url(r'^app02/', include('app02.urls')),
]
URL的命名和反向解析
静态路由
url(r'^publisher_list/', views.publisher_list, name='publisher'),
反向解析
模板
{% url 'publisher' %} ——》 /app01/publisher_list/
py文件
from django.urls import reverse
reverse('publisher') ——》 /app01/publisher_list/
分组
url(r'^(publisher)_list/', views.publisher_list, name='publisher'),
反向解析
模板
{% url 'publisher' 'publisher' %} ——》 /app01/publisher_list/
py文件
from django.urls import reverse
reverse('publisher',args=('publisher',)) ——》 /app01/publisher_list/
命名分组
url(r'^(?P<xx>publisher)_list/', views.publisher_list, name='publisher'),
反向解析
模板
{% url 'publisher' 'publisher' %} ——》 /app01/publisher_list/
{% url 'publisher' xx='publisher' %} ——》 /app01/publisher_list/
py文件
from django.urls import reverse
reverse('publisher',args=('publisher',)) ——》 /app01/publisher_list/
reverse('publisher',kwargs={'xx':'publisher'}) ——》 /app01/publisher_list/
namespace
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01', include('app01.urls',namespce='app01')),
url(r'^app02/', include('app02.urls')),
]
{% url namespace:name %}
reverse('namespace:name ')
今日内容
常用的字段
AutoField 自增 primary_key=True主键
IntegerField 整形 -21亿 - 21亿
BooleanField NullBooleanField 布尔值 0 1
CharField 字符串
TextField 文本类型
DateTimeField DateField TimeField
FloatField 浮点型
DecimalField 十进制小数
字段参数
null=True 数据库中该字段可以为空
blank=True 用户输入可以为空
default 默认值
db_index=True 索引
unique 唯一约束
verbose_name 显示的名称
choices 可选择的参数
使用admin的步骤:
-
创建一个超级用户
python manage.py createsuperuser
输入用户名 和 密码
-
在app下的admin.py中注册model
from django.contrib import admin from app01 import models # Register your models here. admin.site.register(models.Person) -
地址栏输入/admin/
必知必会13条
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
import django
django.setup()
from app01 import models
# all() 获取所有的数据 QuerySet 对象列表
ret = models.Person.objects.all()
# get() 获取一个对象 对象 不存在或者多个就报错
# ret = models.Person.objects.get(name='alexdsb')
# filter() 获取满足条件的所有对象 QuerySet 对象列表
ret = models.Person.objects.filter(name='alexdsb')
# exclude() 获取不满足条件的所有对象 QuerySet 对象列表
ret = models.Person.objects.exclude(name='alexdsb')
# values QuerySet [ {} ]
# values() 不写参数 获取所有字段的字段名和值
# values('name','age') 指定字段 获取指定字段的字段名和值
ret = models.Person.objects.values('name', 'age')
# for i in ret:
# print(i,type(i))
# values_list QuerySet [ () ]
# values_list() 不写参数 获取所有字段的值
# values_list('name','age') 指定字段 获取指定字段的值
ret = models.Person.objects.values_list('age', 'name')
# for i in ret:
# print(i, type(i))
# order_by 排序 默认升序 降序 字段名前加- 支持多个字段
ret = models.Person.objects.all().order_by('-age', 'pk')
# reverse 对已经排序的结果进行反转
ret = models.Person.objects.all().order_by('pk')
ret = models.Person.objects.all().order_by('pk').reverse()
# distinct mysql不支持按字段去重
ret = models.Person.objects.all().distinct()
ret = models.Person.objects.values('name','age').distinct()
# count() 计数
ret = models.Person.objects.all().count()
ret = models.Person.objects.filter(name='alexdsb').count()
# first 取第一个元素 取不到是None
ret = models.Person.objects.filter(name='xxxx').first()
# last 取最后一个元素
ret = models.Person.objects.values().first()
# exists 是否存在 存在是True
ret = models.Person.objects.filter(name='xx').exists()
print(ret)
"""
返回对象列表 QuerySet
all()
filter()
exclude()
values() [ {},{} ]
values_list() [ (),() ]
order_by()
reverse()
distinct()
返回对象
get
first
last
返回数字
count
返回布尔值
exists()
"""
单表的双下划线
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
import django
django.setup()
from app01 import models
ret = models.Person.objects.filter(pk__gt=3) # gt greater than 大于
ret = models.Person.objects.filter(pk__lt=3) # lt less than 小于
ret = models.Person.objects.filter(pk__gte=3) # gt greater than equal 大于等于
ret = models.Person.objects.filter(pk__lte=3) # lt less than equal 小于等于
ret = models.Person.objects.filter(pk__range=[1, 4]) # 范围
ret = models.Person.objects.filter(pk__in=[1, 4]) # 成员判断
ret = models.Person.objects.filter(name__in=['alexdsb','xx'])
ret = models.Person.objects.filter(name__contains='x') # contains 包含 like
ret = models.Person.objects.filter(name__icontains='X') # ignore contains 忽略大小写
ret = models.Person.objects.filter(name__startswith='X') # 以什么开头
ret = models.Person.objects.filter(name__istartswith='X') # 以什么开头
ret = models.Person.objects.filter(name__endswith='dsb') # 以什么开头
ret = models.Person.objects.filter(name__iendswith='DSB') # 以什么开头
ret = models.Person.objects.filter(phone__isnull=False) # __isnull=False 不为null
ret = models.Person.objects.filter(birth__year='2020')
ret = models.Person.objects.filter(birth__contains='2020-11-02')
print(ret)
第六十二章
内容回顾
ORM
对象关系映射 面向对象和关系型数据库
对应关系
类 ——》 表
对象 ——》 数据行(记录)
属性 ——》 字段
常用字段
models.AutoField(primary_key=True)
models.CharField(max_length) # 字符串 varchar(32)
models.TextField
models.BooleanField # 布尔值
models.DateTimeField(auto_now=True)
models.IntegerField # 10 -21亿 + 21亿
models.FloatField
models.DecimalField(max_digits=6,decimal_places=3) # 10进制 999.999
models.ForeignKey
models.ManyToManyField
字段的参数
null=True 数据库中该字段可以为空
blank = True form表单输入时允许为空
default 默认值
unique 唯一
choices 可选的参数
verbose_name 可显示的名字
db_index 数据库索引
db_column 列名
editable 是否可编辑
必知必会13条
返回querySet
all() 所有的对象
filter() 获取满足条件的所有对象
exclude() 获取不满足条件的所有对象
order_by() 排序 -
reverse() 反转
values() [ {} ]
values_list() [ () ]
distinct() 去重
返回对象
get() 获取有且唯一的对象
first()
last()
返回数字
count()
返回布尔值
exists()
单表的双下划线
字段__条件
__gt 大于
__gte 大于等于
__lt 小于
__lte 小于等于
__in= [] 成员判断
__range = [3,6] 范围 3-6
__contains ='' 包含 like
__icontains ='' 忽略大小写
__startswith ='' 以什么开头
__istartswith ='' 以什么开头
__endswith ='' 以什么结尾
__endswith ='' 以什么结尾
__year ='2019'
__isnull = True 字段值为null
外键
# 基于对象的查询
# 正向查询
book_obj = models.Book.objects.get(pk=4)
print(book_obj.name)
print(book_obj.publisher)
print(book_obj.publisher_id)
# 反向查询
pub_obj = models.Publisher.objects.get(pk=1)
# 不指定related_name 表名小写_set
print(pub_obj)
print(pub_obj.book_set) # 表名小写_set 关系管理对象
print(pub_obj.book_set.all())
# 指定related_name=‘books’ 表名小写_set
print(pub_obj.books)
print(pub_obj.books.all())
# 基于字段的查询
# 查询“李小璐出版社”出版社的书
ret = models.Book.objects.filter(publisher__name='李小璐出版社')
# 查询“绿光”书的出版社
# 没有指定related_name 表名小写
ret = models.Publisher.objects.filter(book__name='绿光')
# 指定related_name='books'
ret = models.Publisher.objects.filter(books__name='绿光')
# 指定related_query_name='book'
ret = models.Publisher.objects.filter(book__name='绿光')
print(ret)
多对多
# 基于对象的
author_obj = models.Author.objects.get(name='yinmo')
# print(author_obj.books) # 关系管理对象
# print(author_obj.books.all()) # 所关联的书
book_obj = models.Book.objects.get(name='原谅你')
# print(book_obj.author_set)
# print(book_obj.author_set.all())
# print(book_obj.authors)
# print(book_obj.authors.all())
# 基于字段的查询
# print(models.Author.objects.filter(books__name='原谅你'))
# print(models.Book.objects.filter(author__name='yinmo'))
# all 查询所有的对象
# set() 设置多对多的关系 [id,id] [对象,对象]
# author_obj.books.set([1,3])
# author_obj.books.set(models.Book.objects.filter(pk__in=[2,4]))
# add 新增多对多的关系 id,id 对象,对象
# author_obj.books.add(1,3)
# author_obj.books.add(*models.Book.objects.filter(pk__in=[1,3]))
# remove 删除多对多的关系 id,id 对象,对象
# author_obj.books.remove(1,3)
# author_obj.books.remove(*models.Book.objects.filter(pk__in=[2,4]))
# clear 删除所有多对多的关系
# author_obj.books.clear()
# author_obj.books.set([])
# create 创建一个所关联的对象并且和当前对象绑定关系
# ret = author_obj.books.create(name='yinmo的春天',publisher_id=1)
# print(ret)
pub_obj = models.Publisher.objects.get(pk=1)
print(pub_obj.books.all())
# print(pub_obj.books.set(models.Book.objects.filter(pk__in=[3,4])))
# print(pub_obj.books.add(*models.Book.objects.filter(pk__in=[1])))
# 外键的关系管理对象需要有remove和clear 外键字段必须可以为空
# print(pub_obj.books.remove(*models.Book.objects.filter(pk__in=[1])))
# print(pub_obj.books.clear())
# print(pub_obj.books.create(name="你喜欢的绿色"))
聚合和分组
# 所有的价格
# ret = models.Book.objects.all().aggregate(Sum('price'))
# ret = models.Book.objects.all().aggregate(sum=Sum('price'),avg=Avg('price'),count=Count('pk'))
# ret = models.Book.objects.filter(pk__in=[1,2]).aggregate(sum=Sum('price'),avg=Avg('price'),count=Count('pk'))
# print(ret,type(ret))
# 分组
# 每一本书的作者个数
ret = models.Book.objects.annotate(count=Count('author'))
# 统计出每个出版社买的最便宜的书的价格
# 方式一
ret = models.Publisher.objects.annotate(Min('book__price')).values()
# for i in ret:
# print(i)
# 方拾二
# ret = models.Book.objects.values('publisher__name').annotate(min=Min('price'))
# 统计不止一个作者的图书
ret = models.Book.objects.annotate(count=Count('author')).filter(count__gt=1)
# 查询各个作者出的书的总价格
ret = models.Author.objects.annotate(Sum('books__price')).values()
print(ret)
F和Q
from django.db.models import F, Q
ret = models.Book.objects.filter(sale__gt=F('kucun'))
ret = models.Book.objects.all().update(publisher_id=3)
ret = models.Book.objects.filter(pk=1).update(sale=F('sale')*2+43)
# & 与 and
# | 或 or
# ~ 非 not
# Q(pk__gt=5)
ret = models.Book.objects.filter(Q(~Q(pk__gt=5) | Q(pk__lt=3)) & Q(publisher_id__in=[1, 3]))
print(ret)
事务
from django.db import transaction
try:
with transaction.atomic():
# 一系列的操作
models.Book.objects.update(publisher_id=4)
models.Book.objects.update(publisher_id=3)
int('ss')
models.Book.objects.update(publisher_id=2)
models.Book.objects.update(publisher_id=5)
except Exception as e:
print(e)
1. 简介目录
https://www.cnblogs.com/maple-shaw/p/9029086.html
2. 路由系统
https://www.cnblogs.com/maple-shaw/articles/9282718.html
3. 视图
https://www.cnblogs.com/maple-shaw/articles/9285269.html
4. 模板
https://www.cnblogs.com/maple-shaw/articles/9333821.html
5.ORM
字段和参数:https://www.cnblogs.com/maple-shaw/articles/9323320.html
查询操作:https://www.cnblogs.com/maple-shaw/articles/9403501.html
练习题:https://www.cnblogs.com/maple-shaw/articles/9414626.html
6. cookie和session
https://www.cnblogs.com/maple-shaw/articles/9502602.html
7.中间件
https://www.cnblogs.com/maple-shaw/articles/9333824.html
8. ajax
https://www.cnblogs.com/maple-shaw/articles/9524153.html
9. form组件
https://www.cnblogs.com/maple-shaw/articles/9537309.html
10. auth模块
https://www.cnblogs.com/maple-shaw/articles/9537320.html
第六十三章
cookie
定义:
保存在浏览器本地上的一组组键值对
特性:
1. 服务器让浏览器进行设置的
2. 下次访问时自动携带相应的cookie
在django的操作:
-
获取
request.COOKIES {}
request.COOKIES[] .get
request.get_signed_cookie(key,salt='...',default='xxx')
-
设置
response.set_cookie(key,value)
response.set_signed_cookie(key,value,salt='...')
-
删除cookie
response.delete_cookie(key)
session
定义:
保存在服务器上的一组组键值对,必须依赖cookie
Django的使用:
- 设置
request.session[key] = value
-
获取
request.session[key]
request.session.get(key)
-
其他
del request.session['k1'] # 会话session的key request.session.session_key # 将所有Session失效日期小于当前日期的数据删除 request.session.clear_expired() # 删除当前会话的所有Session数据 request.session.delete() # 删除当前的会话数据并删除会话的Cookie。 request.session.flush() # 设置会话Session和Cookie的超时时间 request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。
session的配置
from django.conf import global_settings
cookie名字
SESSION_COOKIE_NAME = 'sessionid'
超时时间
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2
每次请求保存session
SESSION_SAVE_EVERY_REQUEST = False
浏览器关闭session数据失效
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
存放session的位置
SESSION_ENGINE = 'django.contrib.sessions.backends.db'
第六十四章
cookie和session
cookie
-
定义
保存在浏览器上的一组组键值对
-
为什么要有?
HTTP协议是无状态,每次请求之间都相互独立的,之间没有关系,没办法保存状态。
-
特性:
- 服务器让浏览器进行设置,浏览器有权利不保存
- 下次访问时,自动携带响应的cookie
- 保存在浏览本地的
-
django的操作:
-
设置 set-cookie
response.set_cookie(key,value,max_age=5,path='/')
response.set_signed_cookie(key,value,max_age=5,path='/',salt='xxxxx')
-
获取 cookie
request.COOKIES {}
request.COOKIES[key] request.COOKIES.get(key)
request.get_signed_cookie(key,salt='xxxxx',default=‘’)
-
删除 set-cookie
response.delete-cookie(key')
-
session
-
定义:
保存在服务器上的一组组键值对,必须依赖cookie
-
为什么要有?
- cookie保存在浏览器上,不太安全
- 浏览器对cookie的大小有一定的限制
-
session的流程:
- 浏览器发送请求,没有cookie也没有session
- 要设置session时,先根据浏览器生成一个唯一标识(session_key),存键值对,并且有超时时间
- 返回cookie session_id = 唯一标识
-
在django中的操作:
-
设置
request.session[key] = value
-
获取
request.session[key] request.session.get()
-
删除
del request.session[key]
request.session.pop(key)
request.session.delete() 删除所有的session 不删除cookie
request.session.flush() 删除所有的session 删除cookie
-
其他
request.session.clear_expired() 删除已经失效的session数据
request.session.set_expiry(value)
-
配置
from django.conf import global_settings
SESSION_SAVE_EVERY_REQUEST = True 每次请求都更新session数据
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
SESSION_ENGINE = 'django.contrib.sessions.backends.db' 默认存在数据库
缓存 文件 缓存+数据库 加密cookie
Json序列化的过程
-
中间件
中间件 :中间件就是一个类,在全局范围内处理django的请求和响应。
类 5个方法 4个特点
process_request(self,request)
执行时间:
在视图函数之前
执行顺序:
按照注册的顺序 顺序执行
参数 :
request: 请求的对象,和视图函数是同一个
返回值:
None : 正常流程
HttpResponse:之后中间件的process_request、路由、process_view、视图都不执行,执行执行当前中间件对应process_response方法,接着倒序执行之前的中间件中的process_response方法。
process_response(self, request, response)
执行时间:
在视图函数之后
执行顺序:
按照注册的顺序 倒序执行
参数 :
request: 请求的对象,和视图函数是同一个
response: 响应对象
返回值:
HttpResponse: 必须返回
process_view(self, request, view_func, view_args, view_kwargs)
执行时间:
在路由匹配之后,在视图函数之前
执行顺序:
按照注册的顺序 顺序执行
参数 :
request: 请求的对象,和视图函数是同一个
view_func:视图函数
view_args: 给视图传递的位置参数
view_kwargs: 给视图传递的关键字参数
返回值:
None: 正常流程
HttpResponse: 之后中间件的process_view、视图都不执行,直接执行最后一个中间件process_response,倒序执行之前中间件的process_response方法
process_exception(self, request, exception)
执行时间:
在视图函数出错之后执行
执行顺序:
按照注册的顺序 倒序执行
参数 :
request: 请求的对象,和视图函数是同一个
exception:报错的对象
返回值:
None: 自己没有处理,交给下一个中间件处理,所有的中间件都没有处理,django处理错误。
HttpResponse: 之后中间件的process_exception,直接执行最后一个中间件process_response,倒序执行之前中间件的process_response方法
process_template_response(self,request,response)
执行时间:
当视图函数返回一个TemplateResponse对象
执行顺序:
按照注册的顺序 倒序执行
参数 :
request: 请求的对象,和视图函数是同一个
response:响应的对象
返回值:
HttpResponse: 必须返回
第六十五章
ajax
js的技术,就是发请求接受响应的技术,传输少量的数据。
发请求的途径:
- a标签 get
- 地址栏输入地址 get
- form表单 get / post
特点:
-
局部刷新
-
传输的数据量少
-
异步
简单使用:
$.ajax({
'url':'/calc/',
'type':'post',
'data':{
'k1':$('[name="i1"]').val(),
'k2':$('[name="i2"]').val(),
},
success:function (ret) {
$('[name="i3"]').val(ret)
}
})
参数
$.ajax({
url: '/test/', # 提交的地址
type: 'post', # 请求方式
data: { # 提交的数据
name: 'alex',
age: 73,
hobby: JSON.stringify(['装逼', '画饼', '上过北大'])
},
success: function (ret) { # 响应成功的回调函数
},
error:function (ret) { # 响应失败的回调函数
console.log(ret)
}
})
上传文件
$('button').click(function () {
var form_data = new FormData();
form_data.append('k1','v1');
form_data.append('f1',$('#f1')[0].files[0]);
$.ajax({
url :'/file_upload/',
type:'post',
data:form_data, // { k1:v1 }
processData: false, // 不需要处理数据
contentType: false, // 不需要contentType请求头
success:function (ret) {
console.log(ret)
}
})
})
ajax能通过django的csrf的校验:
前提必须有cookie:
-
给视图加装饰器
from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def index(request):
方式一:data中添加键值对 csrfmiddlewaretoken
$.ajax({
'url': '/calc/',
'type': 'post',
'data': {
'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val(),
'k1': $('[name="i1"]').val(),
'k2': $('[name="i2"]').val(),
},
success: function (ret) {
$('[name="i3"]').val(ret)
}
})
方式二:加请求头 x-csrftoken
$('#b2').click(function () {
// 点击事件触发后的逻辑
$.ajax({
'url': '/calc2/',
'type': 'post',
headers:{'x-csrftoken':$('[name="csrfmiddlewaretoken"]').val(),},
'data': {
'k1': $('[name="ii1"]').val(),
'k2': $('[name="ii2"]').val(),
},
success: function (ret) {
$('[name="ii3"]').val(ret)
}
})
})
方式三:
导入文件
第六十六章
内容回顾
ajax
js技术,发请求。
特点:
-
异步
-
局部刷新
-
数据量小
发请求的方式:
- 地址栏输入地址 get
- a标签 get
- form get /post
- action 提交的地址 method='post' 上传的文件的 enctype="multipart/form-data"
- 有button或者 input类型submit
- input 标签有name属性 有的需要有value
- ajax
简单使用:
使用jq发送ajax请求
$.ajax({
url:'' , // 请求发送的地址
type:'post', // 请求方式
data: {} , // 数据
success:function (res){} // 响应成功之后执行的回调函数 res返回的响应体
})
上传文件
var form_data = new FormData()
form_data.append('k1','v1')
form_data.append('f1',$('#f1')[0].files[0])
$.ajax({
url:'' , // 请求发送的地址
type:'post', // 请求方式
data:form_data , // 数据
processData:false, // 不需要处理数据的编码 multipart/form-data
contentType:false, // 不需要处理contentType的请求头
success:function (res){} // 响应成功之后执行的回调函数 res返回的响应体
})
ajax通过django的csrf的校验
前提:必须要有csrftoken的cookie
方式一:
给data添加csrfmiddlewaretoken键值对
方式二:
给headers 添加 x-csrftoken的键值对
方式三:
导入文件
csrf相关装饰器
from django.views.decorators.csrf import ensure_csrf_cookie,csrf_exempt,csrf_protect
# ensure_csrf_cookie 确保有cookie
# csrf_exempt 不需要进行csrf的校验
# csrf_protect 需要进行csrf的校验
注意: csrf_exempt CBV的时候只能加载dispatch方法上
今日内容
form组件
form
- 有input让用户输入
- 提交数据
form组件
- 提供input框
- 能对数据做校验
- 返回错误提示
定义:
from django import forms
class RegForm(forms.Form):
username = forms.CharField(label='用户名')
password = forms.CharField(label='密码')
使用:
函数
def register2(request):
if request.method == 'POST':
form_obj = RegForm(request.POST)
if form_obj.is_valid(): # 校验数据
# 插入数据库
print(form_obj.cleaned_data)
print(request.POST)
return HttpResponse('注册成功')
else:
form_obj = RegForm()
return render(request, 'register2.html', {'form_obj': form_obj})
模板
{{ form_obj.as_p }} # 展示所有的字段
{{ form_obj.username }} # 生成input框
{{ form_obj.username.label }} # 中文提示
{{ form_obj.username.id_for_label }} # input框的id
{{ form_obj.username.errors }} # 该字段的所有的错误
{{ form_obj.username.errors.0 }} # 该字段的第一个的错误
{{ form_obj.errors }} # 该form表单中所有的错误
常用字段:
CharField # 文本输入框
ChoiceField # 单选框
MultipleChoiceField # 多选框
字段参数:
required=True, 是否必填
widget=None, HTML插件
label=None, 用于生成Label标签或显示内容
initial=None, 初始值
error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'}
disabled=False, 是否可以编辑
validators=[], 自定义验证规则
校验
自定义校验规则
-
写函数
from django.core.exceptions import ValidationError def checkusername(value): # 通过校验规则 什么事都不用干 # bu通过校验规则 抛出异常ValidationError if models.User.objects.filter(username=value): raise ValidationError('用户名已存在') username = forms.CharField( validators=[checkusername,]) -
用内置的校验器
from django.core.validators import RegexValidator phone = forms.CharField(min_length=11,max_length=11,validators=[RegexValidator(r'^1[3-9]\d{9}$','手机号格式不正确')])
局部钩子和全局钩子
def clean(self):
# 全局钩子
# 通过校验 返回self.cleaned_data
# 不通过校验 抛出异常
password = self.cleaned_data.get('password')
re_password = self.cleaned_data.get('re_password')
if password == re_password:
return self.cleaned_data
else:
self.add_error('password','两次密码不一致!!')
raise ValidationError('两次密码不一致')
def clean_username(self):
# 局部钩子
# 通过校验 返回当前字段的值
# 不通过校验 抛出异常
value = self.cleaned_data.get('username')
if models.User.objects.filter(username=value):
raise ValidationError('用户名已存在')
return value
第六十八章
git
版本控制
git init 初始化仓库
git init 文件 创建文件并初始化仓库
git status 查看状态
git add 文件名 /. 将变化的内容添加到暂存区
git commit -m '描述信息' 提交到版本库
git log 查看版本记录
git reflog 查看版本变更记录
git reset --hard 版本号 版本回退
分支
默认 master
git branch 查看所有的分支
git branch 分支 新建分支
git checkout 分支 切换分支
git merge new分支 把new分支合并到当前分支
合并中可能出现冲突 需要手动解决冲突
git stash 把当前的操作藏在某个地方了
git tag 查看所有标签
git tag v1.0 给当前commit 打标签 新建了版本
git checkout -b new_branch 标签
个人开发
master dev debug
dev 的分支上开发功能
合并到master分支上 (master分支放可以上线的代码)
master分支的代码有bug
- 新建一个debug分支
- 切换到debug分支修改bug,提交版本
- 切换回master分支,合并debug分支
dev开发,开发到一半:
1. git stash 隐藏当前的操作
2. 修复完线上的bug,合并debug分支,删除debug分支
3. git stash pop 拿回之前的操作,继续开发
码云 GitHub gitlab
个人 公司 家
公司下班:
git add .
git commit - m '未完成'
git push origin dev
到家接着开发:
下载安装git 配置
git clone https://gitee.com/maple-shaw/day68.git
git branch dev
git checkout dev
git pull origin dev
接着开发功能
开发完成
git add .
git commit - m '功能'
git push origin dev
第二天上班:
git pull origin dev
有冲突解决冲突
继续开发
协同开发
master dev 每个人创建自己的分支
每个人在自己的分支开发功能
开发完成后 add commit 推送到远程仓库自己的分支
提交pull request 合并到dev分支上
github上搜索gitigore找不需要上传的配置文件,将pycharm的.idea/添加进去,就不会上传.idea文件夹
Django项目中 settings中导入自己写的local_settings异常捕获,上传使用settings,测试使用local_settings

浙公网安备 33010602011771号