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