查询API
all(): 查询所有结果
filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误
exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
order_by(*field): 对查询结果排序(‘-id’可以实现倒序)
reverse(): 对查询结果反向排序
count(): 返回数据库中匹配查询(QuerySet)的对象数量
first(): 返回第一条记录
last(): 返回最后一条记录
exists(): 如果QuerySet包含数据,就返回True,否则返回False
values(*field): 返回一个ValueQuerySet》》一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
distinct(): 从返回结果中剔除重复记录
主流web框架总结:
a socket
b 路由关系
c 模板字符串替换(模板语言)
django a用别人的 b自己写的 c自己写的
flask a用别人的 b自己写的 c用别人的(jinja2)
tornado a自己写的 b自己写的 c自己写的
另一个维度:
django
其他
创建Django
#注意:别忘了前面加解释器
1 模块安装
2 django-admin startproject mysite
3 manage.py 管理我的django项目
4 启动django--python3
manage.py runserver 127.0.0.1:8002
-manage.py runserver 8002
-manage.py runserver
(2)pycharm启动:1 跟上面一样
2 点绿色的箭头
不是点右键运行
5 停止 ctrl+c
6 目录介绍
settings--django全局配置文件
urls---路由关系
创建app命令:
manage.py startapp app01
目录:
migrations:数据库迁移的文件
admin:后台管理相关
apps:app配置相关
models:模型,数据库相关,写一些类
继承auth的话,需要导入一下模块
from django.contrib.auth.models import AbstractUser
class user(AbstractUser): #定义自己需要的类,继承AbstractUser
#写自己的功能
test:测试相关
views:视图函数
settings:
DEBUG
INSTALLED_APPS—》放app的名字
MIDDLEWARE–》中间件
TEMPLATES—》指定我模板文件放的路径
DATABASES—》指定连接的数据库
静态文件配置:(名字一定不能错)
STATICFILES_DIRS=[
os.path.join(BASE_DIR, ‘static’),
]
三件套:
render 模板渲染
HttpResponse 返回字符串
redirect 重定向
orm:对象关系映射
python代码------》sql
前端:
$(“#app”)------>document.getElementById(‘app’)
优点:
1 sql掌握一般,也可开发程序
2 开发效率高
3 易用,学习曲线短
缺点:
1 sql大神,执行效率高,可能orm 执行效率低
2 有的sql写不出来
orm能干的事:
1 创建表,修改表,删除表
2 插入数据
3 修改数据
4 删除数据
不能干:不能创建数据库
类名-----》表
对象------》一条数据
属性-----》字段
使用mysql步骤:
1、创建数据库(orm不能创建数据库)
2、在settings里配置
'default': {
'ENGINE': 'django.db.backends.mysql', #注意改后缀名
'NAME': 'mytest', #数据库名称
'HOST': '127.0.0.1', #ip地址
'PORT': 3306, #数据库端口
'USER': 'root', #指定用户
'PASSWORD': 'xxxxxxx' #指定密码
3、在app的init.py文件里写上:
import pymysql
# django 默认用mysqldb连接mysql数据库,但是mysqldb这个模块不支持python3.0以后的版本,
# 所以用pymysql来替换mysqldb
pymysql.install_as_MySQLdb()
4、在models里定义类,类必须继承 models.Model
5、写属性,对应着数据库的字段
6、执行 python manage.py makemigrations(相当于做一个记录)
7、执行 python manage.py migrate (会把记录执行到数据库)
#注意:创建出来的表名是app的名字_类名
2.0 path
1 from django.urls import path
2 不支持正则,精准匹配
3 有5个转换器(int,str,slug,path,uuid)
4 自定义转换器:
4.1 写一个类:
class Test:
regex = '[0-9]{4}'
def to_python(self, value):
# 写一堆处理
value=value+'aaa'
return value
def to_url(self, value):
return '%04d' % value
4.2 from django.urls import register_converter
4.3 register_converter(Test,'ttt')
4.4 path('index/' , views.index,name='index'),
MVC和MTV
M T V
models template views
M V C(路由+views)
models 模板 控制器
视图层:request对象:(method POST GET FILES path get_full_path() )
# form表单,不写method ,默认是get请求
# 1 什么情况下用get:请求数据,请求页面,
# 2 用post请求:向服务器提交数据
# request.GET 字典
# request.POST 字典
# 请求的类型
# print(request.method)
# 路径
# http://127.0.0.1:8000/index/ppp/dddd/?name=xxx
# 协议:ip地址和端口/路径?参数(数据)
# print(request.path)
# print(request.get_full_path())
JsonResponse(向前端页面发json格式字符串)
# dic={'name':'xxx','age':18}
# li=[1,2,3,4]
# # return HttpResponse(json.dumps(li))
# from django.http import JsonResponse
# return JsonResponse(li,safe=False)
CBV(class base view)和FBV(function base view)
cbv:
from django.views import View
class Test(View):
def dispatch(self, request, *args, **kwargs):
# 加点东西
print('111')
obj=super().dispatch(request, *args, **kwargs)
# 加点东西
print('2222')
return obj #不return会报错
def get(self,request):
obj= render(request,'index.html')
print(type(obj))
return obj
def post(self,request):
return HttpResponse('ok')
re_path(r'index/', views.Test.as_view()),#在路由里调用
简单文件上传
1 <form action="" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="name">
密码:<input type="text" name="password">
文件:<input type="file" name="myfile">
<input type="submit">
</form>
#enctype="multipart/form-data" #提交数据必须指定的格式
# #指定类型和名称
2 # ff是一个文件对象,django封装的
ff=request.FILES.get('myfile')
# 文件对象的名字
file_name=ff.name
from django.core.files.uploadedfile import InMemoryUploadedFile
print(type(ff))
with open(file_name,'wb') as f:
for line in ff.chunks():
f.write(line)
基础知识,无名分组:url(r’^admin/', admin.site.urls),
# 第一个参数,可以写一个正则表达式
# 从上往下匹配,一旦匹配成功,就不往下走了
# 如果分几个个组,相应的视图函数,就应该接收几个
# 在setting里设置:APPEND_SLASH=False,请求时,浏览器不会自动补全斜杠,带上斜杠就匹配失败
# 伪静态,方便搜索引擎收录
有名分组:
1 url(r'^test/(?P[0-9]{4})/(?P[0-9]{2})' , views.test)
2 def test(request,month,year):
print(year)
print(month)
return HttpResponse('ok')
#名字必须一致,否则报错,位置可以颠倒,如果分了两个组,必须用两个参数接
3 有名分组和无名分组不要混用
4 有名分组可以用**kwargs接收,无名分组可以用*args接收
5 分组捕获的参数,都是str类型
6 可以设置默认值
路由分发:
1 先导入from django.conf.urls import include
2 url(r'^app01/', include('app01.urls')),有两种方式:。。。。
3 在相应的app里创建urls py文件,建议,不要改名字
4 urlpatterns 不能变名字 ,后面的写法就一样了 url(r'^test',views.test3 ),
5 重复上面步骤,分发多个
2.几和1.几的区别
1 2.几的re_path 就是我原来的url
2 2.几多了一个path,不支持正则
反向解析
1 路由中,命一个名,url(r'^index/', views.index,name='n1'),
2 在视图函数里:
from django.shortcuts import reverse
#这样就能拿到我反向解析出来的url
url=reverse('n1')
3 在模板里用:
{% url 'n1'%}
4 带位置参数反向解析 url(r'^index/([0-9]{4})/([0-9]{2})', views.index,name='n1'),
视图:url=reverse('n1',args=(2012,12,))
模板:{% url 'n1' 2012 12 %}
5 带关键字参数反向解析 url(r'^index/(?P[0-9]{4})/(?P[0-9]{2})' , views.index,name='n1'),
视图:url=reverse('n1',args=(2012,12,) ---可以
url=reverse('n1',kwargs={'year':2014,'month':12})-----也可以
模板:
{% url 'n1' 2012 12 %}----可以
{% url 'n1' month=12 year=2012 %}----可以
注意:按位置传,顺序是固定的
作用:修改路由中url的时候,其它地方不需要改动
名称空间:(知道它,但是建议不同app的url里name不能重名,app的名字_name)
1 url(r'^app01/', include('app01.urls',namespace='app01')),
urlpatterns = [
url(r'^test',views.test3 ,name='test'),
]
url(r'^app02/', include('app02.urls',namespace='app02')),
urlpatterns = [
url(r'^test02',views.test3 ,name='test'),
]
2 在视图函数里:
url=reverse('app02:test')
print(url)
3 在模板里:
<a href="{% url 'app02:test' %}">点我跳到首页</a>
filter
{{}}
1 变量
句点符,深度查询(可以点到方法,不要加括号,只能是无参的方法)
2 过滤器
<p>date过滤器 {{ now|date:'Y-m-d H:i:s' }}</p>
<p>date过滤器 {{ now|date }}</p>
#如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。例如:
<p>default过滤器 {{ ss2|default:'字符串没有值' }}</p>
<p>default过滤器 {{ ll3|default:'列表没有值' }}</p>
#返回值的长度。它对字符串和列表都起作用
<p>length过滤器 {{ ll2|length }}</p>
#将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:
<p>filesizeformat过滤器 {{ file|filesizeformat }}</p>
<p>filesizeformat过滤器 {{ 1024|filesizeformat }}</p>
#切片操作
<p>slice过滤器 {{ 'ycfisbig'|slice:'1:9' }}</p>
#如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾
<p>truncatechars过滤器 {{ 'xxxisbigdddddddeee'|truncatechars:9 }}</p>
<p>truncatewords过滤器: {{ 'xxx is big and yyy is small'|truncatewords:3 }}</p>
<p>safe过滤器: {{ ss3|safe }}</p>
xss攻击:跨站脚本攻击
{#可以在视图函数里处理#}
from django.utils.safestring import mark_safe
ss3=mark_safe(ss3)
<p>safe过滤器: {{ ss3|safe }}</p>
#俩参数可以传字符串和数字,具体详见源码
<p>add过滤器: {{ 12|add:"3" }}</p>
<p>add过滤器: {{ 'eee'|add:"3rrr" }}</p>
tag
{% %}
for :forloop
{%for i in ll%}
#必须再for循环里使用
{{forloop}}
#
{% empty%}}
{% endfor%}
if if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
{%if 条件%}
{% endif%}
{% with aa=dic.name%}
{{aa}}
{%endwith%}
自定义过滤器
1 先去setting里面把app名字配置上
2 再app目录下创建一个templatetags模块
3 写py文件(my_test.py)
4 from django import template
5 register=template.Library()
6 写函数 addstr(用register.filter()装饰)
7 模板:
8 {% load my_test %}
9 {{'xxx'|addstr:'isbig' }} #最多只能传两个参数
自定义标签:
1 先去setting里面把app名字配置上
2 再app目录下创建一个templatetags模块
3 写py文件(my_test.py)
4 from django import template
5 register=template.Library()
6 写函数 [email protected]_tag(name='yy')装饰)
@register.simple_tag(name='yy')
def my_sum(x,y,z,i):
return x+y+z+i
7 模板:
8 {% load my_test %}
9 {% yy 12 34 56 78 %} #以空格做分割,传参数
静态文件引入的三种方式:
一:
<link rel="stylesheet" href="/static/dd/ssmycss.css">
二:
{% load static %}
<link rel="stylesheet" href="{% static 'dd/ss/mycss.css' %}">
{# 返回值:/static/dd/ss/mycss.css#}
三:
<link rel="stylesheet" href="{% get_static_prefix %}dd/ss/mycss.css">
模板导入和继承
模板导入:
1 把公共部分,放到html里,比如叫 left.html
2 想在哪里用 {% include 'left.html' %}
母版继承:
1 写一个母版 base.html
2 要更改的地方写上以下内容
{% block base %}
母版的盒子里也可以写东西
{% endblock %}
3 调用:
3.1 写在第一行 {%extends 'base.html' %}
3.2 {% block base %}
自己的东西
{% endblock my_head%}
3.3 还想用母版里的内容({{block.super}} 放在哪,原来母版里的东西,就会渲染在哪)
{% block base %}
{{block.super}}
自己的东西
{% endblock my_head%}
3.4 如过不继承盒子,它会用原来的内容,如果继承了,没写自己的东西,它会空白
3.5 盒子在继承时,跟顺序无关
自定义 inclusion_tag
1 先去setting里面把app名字配置上
2 再app目录下创建一个templatetags模块
3 写py文件(my_test.py) #可以自定义名字
4 from django import template
5 register=template.Library()
6 @register.inclusion_tag('test.html')
def my_inclusion(n):
data=[]
for i in range(n):
data.append('第%s行'%i)
return {'data':data}
7 写test.html页面
<ul>
{% for choice in data %}
<li>{{ choice }}</li>
{% endfor %}
</ul>
8 {% load my_test %}
9 {% my_inclusion 10 %} 它会返回html的页面
1、 基本应用:
$.ajax({
url:'/ajax_next/', #指定路径
type:'get', #指定get或者post请求
data:{'n1':n1,'n2':n2},
success:function (data) {
alert(data) #处理data
$("#sum").val(data)
}
})
2、提交json数据
#name=xxx&age=12
#往后台传递json格式数据
#JSON.stringify({'name':'ycf'})
#转完之后‘{“name”:“ycf”}’
$.ajax({
url:'/ajax_next/',
type:'get',
contentType:'application/json', #默认是urlencoded
data:JSON.stringify({'name': name, 'pwd': pwd}),
success:function (data) { #success是异步
alert(data) #处理data
$("#sum").val(data)
}
})
需要自己从body取出来,后续处理
3、上传文件:
$(".btn").click(function () {
var formdata=new FormData();
console.log(typeof formdata);
formdata.append('name',$('[name="name"]').val())
formdata.append('pwd',$('[name="pwd"]').val())
formdata.append('myfile',$("#myfile")[0].files[0])
console.log(formdata)
$.ajax({
url: '/ajax_next/',
type: 'post',
contentType: false, //告诉jQuery不要去处理发送的数据
processData:false, // 告诉jQuery不要去设置Content-Type请求头
data: formdata,
success: function (data) {
alert(data)
}
})
})
基于双下划线的模糊查询
Book.ojects.filter(price__in=[100,200,300]) #判断是否在某个值里
Book.ojects.filter(price__gt=100) #大于
Book.ojects.filter(price__lt=100) #小于
Book.ojects.filter(price__gte=100) #大于等于
Book.ojects.filter(price__lte=100) #小于等于
Book.ojects.filter(price__range=[100,200]) #相当于between and
Book.ojects.filter(price__contains="python") #包含
Book.ojects.filter(price__icontains="pyhon") #不区分大小写
Book.ojects.filter(price__startswith="py") #以py开头
Book.ojects.filter(pub_date_year=2021) #匹配年,可以匹配月份,天数
#django聚合
from django.db.models import Avg,Count,Max,Min,Sum #需要导入
#django F和Q
from djngo.d.models import F,Q #/导入F、Q
F()的实例可以在查询中引用字段
Q()来表示与或非 &表示与 |表示或 ~表示非
#不用访问页面,直接写一个py文件,运行就能查看结果
“untitled2.settings”根据自己的配置文件修改名字
import os
if __name__=='__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE","untitled2.settings")
import django
django.setup()
from django.shortcuts import render, HttpResponse
# Create your views here.
from app01.models import * #导入自己定义的类
from django.core.paginator import Paginator, EmptyPage #导入分页码需要的模块
def page_test(request):
# book_list=[] #创建一个空列表
# for i in range(100): #循环一百次
# # Book.objects.create(name='book%s'%i,price=10+i) #这种方式每次都要打开数据库存一条数据,耗费资源
# book=Book(name='book%s'%i,price=10+i) #每循环一次将数据存入book
# book_list.append(book) #添加到列表里
# Book.objects.bulk_create(book_list,10) #统一加入到数据库,10代表一次写入10条
# 获取当前页码
book_list = Book.objects.all() #查询所有数据
paginator = Paginator(book_list, 3) #3代表每页展示多少条数据
print(paginator.count) #传进来的object_list总共的数量
print(paginator.num_pages) #总共的页数
print(paginator.page_range) #页码的列表。比如[1,2,3]
try:
current_page = int(request.GET.get('page', 1))
# 生成page对象,传页码,会生成对应页码数据
page = paginator.page(current_page)
except Exception:
current_page = 1
page = paginator.page(1)
# for i in page.object_list:
# print(i)
# for i in page:
# # 当前页码的每条数据
# print(i)
# 是否有下一页
# print(page.has_next())
# # 是否有上一页
# print(page.has_previous())
# # 下一页页码
# print(page.next_page_number())
# # 上一页页码
# print(page.previous_page_number())
#object_list :在当前这页上的对象列表。
#number :当前的页码。
#paginator :获取 Paginator 对象。
# 显示前5 后5 总共11页
if paginator.num_pages > 11: #判断总页码数是否大于11
if current_page - 5 < 1: #判断当前页码数减5是否小于一
page_range = range(1, 12) #指定范围,顾头不顾尾,共十一页
elif current_page + 5 > paginator.num_pages: 判断当前页码数加5是否大于总页码数
page_range = range(paginator.num_pages - 10, paginator.num_pages + 1) #指定范围,顾头不顾尾,共十一页
else:
page_range = range(current_page - 5, current_page + 6) #除了上面两种情况,则正常显示前五页后五页
else:
page_range = paginator.page_range #页码数不大于十一页,有多少页就显示多少页
return render(request, 'page_test.html', locals()) #locals() 函数会以字典类型返回当前位置的全部局部变量。
forms组件简单介绍
1 字段校验
2 渲染表单
3 显示错信息
4 局部钩子
5 全局钩子
实例
from django import forms #导入表单
from django.forms import widgets #widgets可以指定输入框格式和定义属性
from django.core.exceptions import ValidationError #补货异常需要导入ValidationError
class RegForm(forms.Form): #定义类继承forms.Form
name = forms.CharField(required=True, max_length=10, min_length=2, label='用户名',
error_messages=
{'required': '该字段必填', 'max_length': '超出指定长度', 'min_length': '长度不够'},
widget=widgets.TextInput(attrs={'class':'form-control error','aa':'xxx'})
)
#required=True 该字段默认就是True
max_length=10 #指定该字段的最大长度限制
min_length=2 #指定该字段的最小长度限制
label='用户名' #渲染时在页面会显示
error_messages={} #指定不符合条件时给出的提示
widget=widgets.TextInput(attrs={} #指定input是哪个框,可以自己选,attrs可以自己定义属性,自己通过属性名修改样式
pwd = forms.CharField(max_length=10, min_length=2, label='密码',widget=widgets.PasswordInput(attrs={'class':'form-control error','aa':'xxx'}))
re_pwd = forms.CharField(max_length=10, min_length=2, label='确认密码',widget=widgets.PasswordInput(attrs={'class':'form-control error','aa':'xxx'}))
# xx = forms.CharField(max_length=10, min_length=2, label='确认密码',widget=widgets.CheckboxInput())
email = forms.EmailField(label='邮箱', error_messages={'required': '该字段必填', 'invalid': '不符合邮箱格式'},widget=widgets.EmailInput(attrs={'class':'form-control error','aa':'xxx'}))
# 局部钩子(多了一个我自己写校验规则的方式)
def clean_name(self): #要修改的字段必须是clean_(自己上面定义过得名称)
name=self.cleaned_data.get('name') #cleaned_data是用来存储已经校验通过的数据
user=UserInfo.objects.filter(name=name).first() #通过上面拿出来的数据和自己数据库中的数据做对比
if user:
raise ValidationError('用户已经存在') #比对成功则显示用户已经存在
else:
if name.startswith('sb'):
raise ValidationError('不能以sb开头') #也可以自己限制不让用户输入的格式
return name
# 全局钩子
def clean(self): #全局钩子是上面所有都校验通过之后才能到达的
pwd=self.cleaned_data.get('pwd') #因为上面没有校验密码的error_message,所以可以在这里进行判断
re_pwd=self.cleaned_data.get('re_pwd')
if pwd and re_pwd:
if pwd==re_pwd:
return self.cleaned_data
else:
raise ValidationError('两次密码不一致')
# def forms_test(request):
# # from类里没有的字段,不会做校验,而且,一旦校验通过,cleaned_data 里面也没有这个字段
# # from类里有的字段,如果不传,一定校验不通过
# # form_obj=RegForm({'namea':'leee','password':'xxx','email':'[email protected]','xxx':'xxx'})
# # # 返回一个布尔类型,true代表,里面所有字段,都校验通过
# # print(form_obj.is_valid())
# # if form_obj.is_valid():
# # # 校验通过的字段,放在里面
# # print(form_obj.cleaned_data)
# # else:
# # print(form_obj.errors.get('name')[0])
# # print(type(form_obj.errors))
# # from django.forms.utils import ErrorDict
# # print(form_obj.cleaned_data)
#
#
# return render(request,'forms_test.html')
def forms_test(request): #定义函数
form_obj = RegForm() #指定一个为空的数据
if request.method == 'POST': #来的是post请求则继续往下
form_obj = RegForm(request.POST) #将post请求的数据写入form_obj
if form_obj.is_valid(): #判断是否校验通过
UserInfo.objects.create(**form_obj.cleaned_data) #将数据打散,创建该信息
# return HttpResponse('ok')
else:
print(form_obj.errors.as_data())
errors=form_obj.errors.get('__all__','') #将错误信息返回,可以指定默认为空
# print(form_obj['name'].errors)
# return HttpResponse('失败')
return render(request, 'forms_test.html', locals())
注意:form表单还是需要自己创建
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form action="" method="post"> #正常写入表单以及数据
<p>用户名:<input type="text" name="name" class="form-control" aa="ddd"></p>
<p>密码:<input type="password" name="pwd"class="form-control"></p>
<p>确认密码:<input type="password" name="re_pwd"class="form-control"></p>
<p>邮箱<input type="text" name="email" class="form-control"></p>
<input type="submit">
</form>
<hr>
<h1>渲染页面方式一</h1> #以视图里的字段坐渲染
<form action="" method="post" novalidate>
<p>{{ form_obj.name.label }}:{{ form_obj.name }} <span
class="pull-right">{{ form_obj.name.errors.0 }}</span></p>
<p>密码:{{ form_obj.pwd }}<span class="pull-right">{{ form_obj.pwd.errors.0 }}</span></p>
<p>确认密码:{{ form_obj.re_pwd }}<span class="pull-right">{{ form_obj.re_pwd.errors.0 }}{{ errors }}</span></p>
<p>邮箱{{ form_obj.email }}<span class="pull-right">{{ form_obj.email.errors.0 }}</span></p>
<input type="submit">
</form>
<hr>
<h1>渲染页面方式二</h1> #for循环每个字段,推荐使用,可以在每个字段加入标签,方便改动
<form action="" method="post" novalidate>
{% for foo in form_obj %}
<div>{{ foo.label }}{{ foo }}<span class="pull-right">{{ foo.errors }}</span></div>
{% endfor %}
<input type="submit">
</form>
<hr>
<h1>渲染页面方式三</h1> #不推荐使用,虽然用起来方便,但是没法修改样式
<form action="" method="post">
{{ form_obj.as_p }}
</form>
</div>
</div>
</div>
简单设置
cookie sessioon
#设置cookie
obj.set_cookie(key,value)
return obj
#取cookie
key=request.COOKIES.get('key')
#删除
obj.delete_cookie(’key‘)
retrun obj
#设置session
request.session[key]=value
1
2
3
cbv加装饰器
def login_auth(func):
def inner(request, *args, **kwargs):
url = request.get_full_path()
# /shopping/?nana=ppp
is_login = request.COOKIES.get('is_login')
# xxx=request.get_signed_cookie('xxx',salt='123')
# print(xxx)
if is_login:
ret = func(request,*args, **kwargs)
else:
return redirect('/login/?next=%s' % url)
# /login/?next=/shopping/?nana=ppp
return ret
return inner
def login(request):
if request.method == 'POST':
url = request.GET.get('next')
name = request.POST.get('name')
pwd = request.POST.get('pwd')
if name == 'ycf' and pwd == '123':
obj = redirect(url)
obj.set_cookie('is_login', True,path='/shopping/')
import datetime
now = datetime.datetime.now().strftime('%Y-%m-%d %X')
obj.set_cookie('last_time', now)
obj.set_cookie('name', 'ycf')
obj.set_cookie('pwd', '123')
obj.set_signed_cookie('xxx','xxxxxx',salt='123')
return obj
else:
obj = HttpResponse('登陆失败')
return obj
return render(request, 'login.html')
def logout(request):
obj=HttpResponse('注销成功')
obj.delete_cookie('is_login')
return obj
@login_auth
def shopping(request):
return render(request, 'shopping.html', locals())
@login_auth
def order(request):
return render(request, 'order.html', locals())
from django.utils.decorators import method_decorator
from django.views import View
# @method_decorator(login_auth,name='post')
# @method_decorator(login_auth,name='get')
class MyOrder(View):
@method_decorator(login_auth)
def dispatch(self, request, *args, **kwargs):
ret=super().dispatch(request, *args, **kwargs)
return ret
# 在cbv上加装饰器,需要用method_decorator修饰一下
def get(self,request):
return HttpResponse('get')
def post(self,request):
return HttpResponse('post')
'''
1 导入from django.utils.decorators import method_decorator
2 加载get,post,dispatch方法上:@method_decorator(login_auth)
3 加在类上:@method_decorator(login_auth,name='get')
'''
def session_test(request):
request.session['username']='ycf'
request.session['is_login']=True
'''
1 生成一个随机字符串
2 把随机字符串以cookie的形式写回给浏览器
3 会在数据库里存{'随机字符串':{'username':'ycf','is_login':True}}
'''
return HttpResponse('ok')
def get_session(request):
name=request.session['username']
is_login=request.session['is_login']
print(name)
print(is_login)
# request.session['k1']
# request.session.get('k1', None)
# request.session['k1'] = 123
# request.session.setdefault('username', 123) # 存在则不设置
# del request.session['k1']
# print(request.session.session_key)
# 将所有Session失效日期小于当前日期的数据删除
# request.session.clear_expired()
# print(request.session.exists("uhsvmv7wc41pneeee6f4w0fxvqy6qzh5m29"))
# 会删除数据库的session
# request.session.delete()
# 删除当前的会话数据并删除会话的Cookie。
# 通常用它
request.session.flush()
return HttpResponse('ok')
def test(request):
return HttpResponse('ok')
中间件:
中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能1
重点方法:
请求:process_request 一旦有返回值,直接就回去了
相应:process_response 如果没有返回值,就会报错
process_view
process_exception
Csrf:跨站请求伪造
比如:招商银行转账接口:transfer/?to='xxx'&count='100'
黑客网站:有个按钮:http://market.cmbchina.com/transfer/?to='xxx'&count='100'
XSS:跨站脚本攻击
CBV局部使用,禁用csrf
from django.views import View
from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django.utils.decorators import method_decorator
#加在类上,必须指定方法为dispatch
#@method_decorator(csrf_exempt,name='dispatch')
class Test(View):
#加在dispatch方法上
# @method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
obj=super().dispatch(request, *args, **kwargs)
return obj
def get(self,request):
return render(request,'index1.html')
def post(self,request):
print(request.POST)
return HttpResponse('ok')
首先在你自己新增的app里创建urls.py文件,添加如下内容
from app01 import views #导入自己的视图
from newdjango.urls import path #导入主路由的地址
urlpatterns = [
path('index/', views.index),
]
在views.py里写自己定义的函数
def index(request):
return render(request,'index.html')
在主路由里配置一下内容
from django.urls import path,include #导入include模块
urlpatterns = [
path('admin/', admin.site.urls),
path('app01/',include('app01.urls')), #定义访问路径,include(指定app的路由)
]
web访问的时候app01/index/ #主路由定义的地址/app路由定义的地址