Django基础及实战
day52
今日内容
内容规格
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 项目名
-
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返回给浏览器
day53
内容回顾
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收发消息
- 根据不同路径返回不同的结果(返回HTML页面)
- 返回动态的页面( 模板的渲染 字符串的替换 )
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" 请求方式
- input需要有name属性 value值
- 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') # 获取满足条件的所有对象 对象列表
day54
内容回顾
-
下载
命令行:
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() # 将修改提交的数据库
day55
内容回顾
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 %}
day56
内容回顾
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)
周末
学员管理系统
学生表 班级表 教师表
day57
内容回顾
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' }}
day58
内容回顾
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:‘参数’ }}
今日内容
{% %} tag
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 %}
day59
内容回顾
模板
变量
{{ 变量 }}
.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: 地址
day60
内容回顾
视图
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' 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/'
命名分组
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' )
day61
内容回顾
路由系统
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 可以为空的布尔值
CharField 字符串
TextField 文本类型
DateTimeField 日期+加时间
DateField 日期格式
TimeField 时间格式
FloatField 浮点型
DecimalField(max_difits=6,decimal_piaces=3) 十进制小数
字段参数
null = True 数据库中该字段可以为空
black = True 用户输入可以为空
default 默认值
db_index=True 索引
unique 唯一约束
verbose_name 显示的名称
choices 可选择的参数
使用admin的步骤:
-
创建一个超级用户
python manage.py createsuperuser 输入用户名及密码
2.在app下的admin.py 中注册model
from django.contrib import admin
from app01 import models
#Register your models here.
admin.site.register(models.Person)
3.地址栏输入/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)
188 0133 8917
188 4321 2314
186 2314 3200
day62
内容回顾
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)
day63
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)
from django.shortcuts import render, redirect, HttpResponse from functools import wraps # Create your views here. def is_loging(func): @wraps(func) def inner(request, *args, **kwargs): is_login = request.COOKIES.get('is_login') if is_login != 'true': return redirect('/login/?indexUrl'.format(request.path_info)) #request.path_info 帮助生成url ret = func(request, *args, **kwargs) return ret return inner def login(request): if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') if user == 'alex' and pwd == 'alex3714': # 保存登录状态 设置 cookie returnUrl = request.GET.get('indexUrl') ret = redirect( returnUrl if returnUrl else '/home/') #获取GET请求中的url地址,有地址的返回url携带的地址,如果没有就走home地址 ret.set_cookie('is_login', 'true') return ret return render(request, 'login.html', {'error': '用户名密码错误'}) return render(request, 'login.html') @is_loging def home(request): return HttpResponse('这是home页面')
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'
day64
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: 必须返回
返回值可以是别人传过来的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: 必须返回
day65
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)
}
})
})
方式三:
导入文件
day66
内容回顾
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框
- 能对数据做校验
- 返回错误提示
定义:定义是在views.py中
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
局部钩子
#小点:
自定义的函数校验器,需要填红色的框框,也是针对于某一个字段,别的字段要用,就得加validators=[自定义校验器函数]
form组件,局部钩子,只针对于某一个字段进行校验
上面这个局部钩子只是正对于username这个字段进行的校验!
day67
django web框架
功能
- socket收发消息 wsgi
- 根据不同的路径返回不同的内容
- 返回动态页面(字符串的替换 模板的渲染)
在浏览器上的地址输入地址回车会发生什么事情?
HTTP协议
超文本传输协议 规定请求和响应的格式
请求(浏览器发送给服务器的消息 request)
格式:
'请求方式 URL路径 HTTP/1.1
K1: v1
k2: v2
请求体(请求数据)' // get方法没有请求体
响应(服务器返回给浏览器的消息 response)
格式
‘HTTP/1.1 状态码 状态描述
K1: v1
k2: v2
响应体(响应数据)’
请求方式:8种 GET POST PUT DELETE HEAD OPTION TRACE CONNECT
状态码:
1xx 请求已经接受 还需要进一步的处理
2xx 请求正常接受并且响应
3xx 重定向 301 302
4xx 请求的错误 403 404 402
5xx 服务器的错误 500 502
头:
location 重定向
cookie set-cookie
x-csrftoken
content-type text/html applicaton/json
user-agent
host
url地址:
https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu
http 80
https 443
django
路由
URL地址和函数的对应关系
URLconf
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^publisher/(\d+)/$',views.register ),
url(r'^register2/$',views.register2 ),
]
正则表达式
^ $ \d \w ? + * . |
分组和命名分组
捕获参数 ?id=1111
分组 () 按照位置传参 传给视图
命名分组 (?P
路由分发 include
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/',include('app01.urls') ),
]
app01 urls.py
urlpatterns = [
url(r'^register2/$',views.register2 ),
]
URL的命名和反向解析
静态路由
命名
url(r'^register2/$',views.register2,name='reg' ),
反向解析
模板
{% url 'reg' %} # '/app01/register2/'
py文件
from django.urls import reverse
reverse('reg') # '/app01/register2/'
分组
命名
url(r'^register(\d+)/$',views.register2,name='reg' ),
反向解析
模板
{% url 'reg' 20 %} # '/app01/register20/'
py文件
from django.urls import reverse
reverse('reg',args=('30',)) # '/app01/register30/'
命名分组
命名
url(r'^register(?P<pk>\d+)/$',views.register2,name='reg' ),
反向解析
模板
{% url 'reg' 20 %} # '/app01/register20/'
{% url 'reg' pk=20 %} # '/app01/register20/'
py文件
from django.urls import reverse
reverse('reg',args=('30',)) # '/app01/register30/'
reverse('reg',kwargs={‘pk’:'30'} # '/app01/register30/'
namespace
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/',include('app01.urls',namespace='app01') ),
url(r'^app02/',include('app02.urls',namespace='app02') ),
]
反向解析
{% url 'app01:reg' 20 %}
reverse('app01:reg',args=('30',))
视图
MVC
MTV
view 逻辑 接受请求返回响应
FBV CBV
def xxx(request,*args,**kwargs):
# 逻辑
return response
url(r'^xxx/',xxx ),
from django.views import View
class Class(View):
def get(self,request,*args,**kwargs):
# 处理get请求的逻辑
self.request
return response
def post(self,request,*args,**kwargs):
# 处理post请求的逻辑
return response
url(r'^xxx/',Class.as_view()),
加装饰器
from django.utils.decorators import method_decorator
-
加在方法上
@method_decorator(timer) def get(self,request,*args,**kwargs):
-
加在类上
@method_decorator(timer,name='get') @method_decorator(timer,name='post') class Class(View):
-
加在dispatch
@method_decorator(timer,name='dispatch') class Class(View):
request
request.POST # POST提交的数据 {} urlencode编码
request.GET # url上携带的参数 ?id=1 {id:1}
request.method # 请求方法 GET POST
request.path_info # 路径信息 不包含IP和端口 也不包含查询参数
request.FILES # 上传的文件 enctype='form-data'
request.session # {} session
request.COOKIES # cookie
request.META # 请求头的信息 HTTP_ 小写——》 大写 - ——》 _
request.body # 请求体 原始数据
request.get_full_path() # 完整的路径信息 不包含IP和端口 包含查询参数
request.is_ajax() # 是否是ajax请求
request.get_signed_cookie(key,salt,defalut='')
response
HttpResponse('字符串') # 字符串
JsonResponse({}) JsonResponse([],safe=False)
render(request,'模板文件的路径',{}) # 返回页面 已经替换好了
redirect('地址或者URLname') # 重定向 响应头Location:地址 301 302
TemplateResponse(request,'模板文件的路径',{}) # 后续在调用render方式进行渲染
模板
html + 特殊的语法
变量
{{ }} 变量 {% %}
.key .属性 .方法 .索引
过滤器
内置过滤器
safe default filesizeformat date:'Y-m-d H:i:s' add length slice:'::' join
标签
for forloop
for ... empty
if
不支持算数运算 连续判断
母版和继承
母版:
1. 写上一个HTML页面,包含多个页面的公共部分
2. 定义多个block块,让子页面进行重写
继承:
1. {% extends '母版的路径' %}
2. 重写block块
组件
一段HTML代码 ——》 文件 nav.html
页面 {% include ‘nav.html’ %}
静态文件
{% load static %}
{% static '相对路径' %}
{% get_static_prefix %} # STATIC_URL ='/static/'
自定义的方法
filter、simple_tag 、inclusion_tag
定义:
-
在已经注册的APP下创建templatetags的python包;
-
在python包中创建py文件(自己定义my_tags)
-
写代码
from django import template register = template.Library()
-
写函数 +加装饰器
@register.filter def add_arg(value,arg): return 'xxxx' @register.simple_tag def joins(*args,**kwargs): return 'xxxxxxx' @register.inclusion_tag('li.html') def show_li(*args,**kwargs): return {'li':[1,2]} li.html {% for i in li %} {{ i }} {% endfor %}
使用:
模板
{% load my_tags %}
{{ a|add_arg:'xxx' }} # 'xxxx'
{% joins 'v1' 'v2' k1='v3' k2='v4' %} # 'xxxxxxx'
{% show_li 3 %} # 1 2
ORM
对象关系映射
对应关系
类 ——》 表
对象 ——》 数据行(记录)
属性 ——》 字段
必知必会13条
返回对象列表 QuerySet
all
filter
exculde
values 【{}】
values_list 【() 】
order_by()
reverse()
distinct 去重
返回对象
get
first
last
返回布尔值
exists
返回数字
count
单表的双下划线
__gt 大于
__gte 大于等于
__lt 小于
__lte 小于等于
__in= [] 在不在成员判断
__range = [1,6] 范围
__startswith 以什么开头 __istartswith 以什么开头
__endswith 以什么结尾 __iendswith 以什么结尾
__contains 包含 like __icontains
__year 年
__isnull=True
外键的操作
class Book(models.Model):
name= models.CharField(max_length=32)
pub= models.ForginKey(to='Publisher',on_delete=models.CASCADE,related_name='books')
基于对象
正向
book_obj.pub ——》 关联的出版社对象
book_obj.pub_id ——》 关联的出版社对象id
反向
不指定 related_name
pub_obj.book_set ——》 关系管理对象
pub_obj.book_set.all() ——》 关联的所有的书籍对象 表名_set
指定related_name='books'
pub_obj.books.all() ——》 关联的所有的书籍对象 related_name
基于字段
models.Book.objects.filter(pub__name='xxx')
models.Publisher.objects.filter(book__name) 不指定 related_name
models.Publisher.objects.filter(books__name) 指定 related_name='books'
多对多
class Book(models.Model):
name= models.CharField(max_length=32)
class Author(models.Model):
name= models.CharField(max_length=32)
books= models.ManyToManyField('Book',related_name='authors')
all()
set([]) [对象,对象] [id,id ]
add()
remove()
clear()
create()
聚合和分组
from django.db.models import Max,Min,Count,Avg,SumHobby.objects.all().aggregate(max=Max('filed')) # {max:'xxx' }
Author.objects.annotate(count=Count('books')) # 对象列表
Book.objects.values('authors__name').annotate(Min('price')) # [{}]
F和Q
Book.objects.update(price=F('price')+2)
Q(Q(price__gt=10)|Q())
| 或
& 与
~ 非
事务
一系列的操作 要么都成功,要么都失败。
from django.db import transaction
try:
with transaction.atomic():
# 一系列操作
pass
except Exception as e:
print(e)
中间件
处理django请求和响应的框架级别的钩子。
5个方法 4个特征
cookie和session
为什么要有cookie?
定义:保存在浏览器上一组组键值对
特点:
1. 由服务器让浏览器进行设置
2. 保存在浏览器本地的
3. 下次访问时自动携带对应的cookie
django中的操作:
-
设置 set-cookie
response.set_cookie(key,v,max-age=5,path='/')
-
获取
request.COOKIES[] get()
-
删除 set-cookie
response.delete_cookie(key)
session
为什么要有session?
定义:保存在服务器上一组组键值对,必须依赖cookie
django中的操作:
-
设置
request.session[key] = value
-
获取
request.session[key] request.session.get(key)
-
删除
del request.session[key]
request.session.pop(key)
request.session.delete()
request.session.flush()
request.session.clear_expired() # 删除已经过期的数据
-
request.session.set_expiry()
配置
引擎 SESSION_ENGINE 位置 数据库 缓存 文件 缓存+数据库 加密cookie
SESSION_SAVE_EVERY_REQUEST = True
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
json序列化
ajax
js技术 ,发请求。
$.ajax({
url: 地址,
type: 请求方式,
data : {},
success:function (res){
# 逻辑
$(this)
}
})
$.ajax({
url: 地址,
type: 请求方式,
data : {},
success: (res) => {
# 逻辑
$(this)
}
})
ajax通过django的csrf的校验
- 给data 加
- 加请求头 x-csrftoken
form
功能:
- 提供input框
- 校验forms
- 错误提示
from django import forms
class RegForm(forms.Form):
name = forms.CharField(widget=)
def clean_字段名(self):
# 校验规则
# 通过校验 返回当前字段的值
# 不通过校验 抛出异常
def clean(self):
# 校验规则
# 通过校验 返回所有字段的值self.cleaned_data
# 不通过校验 抛出异常 __all__ self.add_error('字段',’错误信息‘)
label 中文提示
initial 初始值
required 必填
error_messages = { }
disabled
validators 校验器
视图
form_obj = RegForm()
form_obj = RegForm(request.POST)
form_obj.is_valid()
form_obj.cleaned_data 通过校验的数据
模板
{{ form_obj.as_P }}
{{ form_obj.name }} input框
{{ form_obj.name.label }} 中文提示
{{ form_obj.name.id_for_label }} input框的id
{{ form_obj.name.errors }} 当前字段的所有错误
{{ form_obj.name.errors.0 }} 当前字段的第一个错误
{{ form_obj.errors }} 所有字段的所有错误
校验顺序
每个字段:
内置校验规则 field.validate(必填 长度 )
校验器field.run_validators(默认校验器,自定义的校验器)
局部钩子form_obj.clean_字段名
全局钩子 orm_obj.clean