Django笔记

1.前期准备

1.1相关链接

Django官网:https://www.djangoproject.com/
Django中文文档参考网站:https://yiyibooks.cn
django与python版本的对应关系:

Django versionPython version
2.23.5,3.6,3.7,3.8(added in 2.2.8)
3.0,3.1,3.23.6,3.7,3.8

1.2Django安装

在线安装:

# 建议使用pip命令安装:
pip install django==2.2.* 
# 检测当前是否安装Django及版本
python -m django --version

1.3创建项目、启动、创建应用

  • 1.创建项目
django-admin startproject 项目名
  • 2.启动项目
    注意:先进入该项目目录
# 启动项目(先进入项目目录)(端口号不指定默认是8000)
python manage.py runserver
python manage.py runserver 9000
# 1.在使用远程访问的时候,代码中的settings文件夹中,也要把ALLOWED_HOSTS中增加该ip地址ALLOWED_HOSTS = ['192.168.0.108']
# 2.如果全部可以访问,可以直接这样 ALLOWED_HOSTS = ['*']
python manage.py runserver 0.0.0.0:9000 
  • 3.创建一个应用程序
    注意:先进入该项目目录
python manage.py startapp myapp
  • 4.目录结构如图所示:
    在这里插入图片描述

2.框架初识

2.1路由

1.在应用程序myapp中创建urls.py文件

from django.urls import path

from . import views

urlpatterns = [
    path('add', views.add, name='add'),
    path(路径,函数名,名字)
]

2.在总的路由文件中声明,能够找到应用程序的路由文件

from django.contrib import admin
from django.urls import include,path

urlpatterns = [
    # path('admin/', admin.site.urls),
    path('myapp/', include('myapp.urls')),
]

2.2连接MySQL数据库

说明:默认情况下,配置使用SQLite。若不使用SQLite作为数据库,则需要额外的设置,例如 USER,PASSWORD和HOST必须加入。

其中ENGINE设置为数据库后端使用。内置数据库后端有:

‘django.db.backends.postgresql’
‘django.db.backends.mysql’
‘django.db.backends.sqlite3’
‘django.db.backends.oracle’

  • 1.在myweb/settings.py文件中,通过DATABASES项进行数据库设置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydemo',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

注意:Django使用MySQL数据库需要加载 MySQLdb模块,需要安装 mysqlclient,若已经安装请略过。

pip install  mysqlclient
  • 2.创建模型
    在myapp/models.py文件中创建数据库相应类的映射
from django.db import models

# Create your models here.

class Stu(models.Model):
    '''自定义Stu表对应的Model类'''
    #定义属性:默认主键自增id字段可不写
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)
    age = models.SmallIntegerField()
    sex = models.CharField(max_length=1)
    classid=models.CharField(max_length=8)

    # 定义默认输出格式
    def __str__(self):
        return "%d:%s:%d:%s:%s"%(self.id,self.name,self.age,self.sex,self.classid)

    # 自定义对应的表名,默认表名:myapp_stu
    class Meta:
        db_table="stu"
  • 3.激活模型
    在myweb.settings.py中,增加一条记录
INSTALLED_APPS  =  [ 
    'django.contrib.admin''django.contrib.auth''django.contrib.contenttypes''django.contrib.sessions''django.contrib.messages''django.contrib.staticfiles''myapp.apps.MyappConfig',  #或者直接写 myapp
]
  • 4.在views.py文件中测试
from myapp.models import Stu

def add(request):
    lists = Stu.objects.all()
    for stu in lists:
        print(stu)
    print(Stu.objects.get(id=1))
    return HttpResponse("add.")

3.框架详细使用

3.1URL路由

3.1.1如何处理一个请求

  • 1.首先通过settings.py文件中ROOT_URLCONF来设置,找到路由文件。

  • 2.Django加载该Python模块并查找该变量 urlpatterns。它是django.urls.path()和(或)django.urls.re_path()实例的序列(sequence)。

  • 3.Django按 顺序 运行每个URL模式,并在匹配所请求的URL的第一个URL中停止。

  • 4.一旦正则表达式匹配,Django将导入并调用给定的视图,这是一个简单的Python函数(或基于类的视图)。该视图会获得如下参数:
    ① 一个HttpRequest实例。
    ② 如果匹配的正则表达式没有返回任何命名组,那么来自正则表达式的匹配将作为位置参数提供。
    ③ 关键字参数由正则表达式匹配的任何命名组组成,由可选kwargs参数中指定的任何参数覆盖。django.urls.path()、django.urls.re_path()。

  • 5.如果没有正则表达式匹配,或者在此过程中的任何一点出现异常,Django将调用适当的错误处理视图。

3.1.2传参示例

  • 1.在urls.py文件中
urlpatterns = [
    path('', views.index),
    path('add/', views.add),
    path('add/<int:sid>', views.add),
    path('add/<int:sid>/<str:name>', views.add),
]
  • 2.views.py文件中:
def add(request, sid=0, name=''):
    result = "add." + str(sid) + " " + name
    return HttpResponse(result)

注意:

要从URL捕获一个值,请使用 尖括号 括起来。
捕获的值可以选择包括转换器类型。例如,用于<int:name>捕获整数参数。如果不包括转换器/,则匹配除字符以外的任何字符串。
无需添加斜杠,因为每个URL都有该斜杠。例如articles,不是/articles。

  • 3.路径转换器

str-匹配任何非空字符串,但路径分隔符除外’/'。如果表达式中不包含转换器,则为默认设置。
int-匹配零或任何正整数。返回一个int。
slug-匹配由ASCII字母或数字以及连字符和下划线字符组成的任何条形字符串。例如, building-your-1st-django-site。
uuid-匹配格式化的UUID。为防止多个URL映射到同一页面,必须包含破折号并且字母必须小写。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID实例。
path-匹配任何非空字符串,包括路径分隔符 ‘/’。这样,您就可以匹配完整的URL路径,而不是像一样匹配URL路径的一部分str。

3.1.3传参示例(正则)

如果路径和转换器语法不足以定义URL模式,则还可以使用正则表达式。为此,请使用re_path()代替path()。
在Python正则表达式中,命名正则表达式组的语法为(?P<name>pattern),其中name是组的名称,并且 pattern是匹配的某种模式。

这是前面的示例URLconf,使用正则表达式重写:(如果不写尖括号,?p也得去掉)

urlpatterns = [
    path('', views.index),
    re_path(r'^find/$', views.find),
    re_path(r'^find/(?P<year>[0-9]{4})/$', views.find),
    # 如果不起名,?P<year>都去掉,直接写正则表达式(不推荐)
    # re_path(r'^find/([0-9]{4})/$', views.find)
]

3.1.4错误处理(404)

一些变量

handler400- 见django.conf.urls.handler400。
handler403- 见django.conf.urls.handler403。
handler404- 见django.conf.urls.handler404。
handler500- 见django.conf.urls.handler500。

关于404页面问题
该配置在 上线的时候采用 ,开发的时候可以不开,才能更方便的看出错信息。

(1) 在配置文件中 settings.py 配置 DEBUG = False
(2) 在配置文件中 settings.py 配置 TEMPLATES = [{ ‘DIRS’: [os.path.join(BASE_DIR, ‘templates’)], }] (注意:templates是自己取的名,配置模板目录)
(3) 同时需要在项目的根目录下创建文件夹templates,并且在此目录下创建一个404.html文件
(4) 在出现404的情况时,自动寻找404页面。
(5) 也可以在视图函数中 手动报出404错误,带提醒信息

3.1.5URL的反向解析

如果在视图、模板中使用硬编码的链接,在urlconf发生改变时,维护是一件非常麻烦的事情

解决:在做链接时,通过指向urlconf的名称,动态生成链接地址
视图:使用django.urls.reverse()函数
模板:使用url模板标签

urls.py文件中

urlpatterns = [
    path('add/', views.add, name='add1'),
    path('add/<int:sid>/<str:name>', views.add, name='add2'),
]

在view.py文件中使用

from django.shortcuts import redirect # 重定向跳转
from django.urls import reverse

def add(request,sid=2022,name=''):
    year = 2019
    reverse('add1'# 反向生成url地址
    reverse('add2',args=(sid,name)) # 反向生成url地址,有参数需要加参数
    reverse('add2',args=(100,'李四')) # 举例
    return redirect(reverse('add2',args=(sid,name)))

3.2Django的模型层

3.2.1迁移文件生成与迁移

一般不用,一般是先创建数据库,然后使用。
首先按照框架初始章节,对数据库进行连接。如果数据库中没有表,可以在myapp/models.py文件中进行编写,然后生成迁移文件并执行迁移。这个时候数据库中也会增加数据库表。

# 1.生成迁移文件
python manage.py makemigrations
# 2.执行迁移
python manage.py migrate

3.2.2字段相关介绍

注意:django会为表增加自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后,则django不会再生成默认的主键列
字段类型:

AutoField: 一个根据实际ID自动增长的IntegerField,通常不指定;如果不指定,一个主键字段将自动添加到模型中
BooleanField: true/false 字段,此字段的默认表单控制是CheckboxInput
NullBooleanField: 支持null、true、false三种值
CharField(max_length=字符长度): 字符串,默认的表单样式是 TextInput
TextField: 大文本字段,一般超过4000使用,默认的表单控件是Textarea
IntegerField: 整数
DecimalField(max_digits=None, decimal_places=None): 使用python的Decimal实例表示的十进制浮点数
DecimalField.max_digits: 位数总数
DecimalField.decimal_places: 小数点后的数字位数
FloatField: 用Python的float实例来表示的浮点数
DateField[auto_now=False, auto_now_add=False]): 使用Python的datetime.date实例表示的日期
①参数DateField.auto_now:每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false
②参数DateField.auto_now_add:当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false
③该字段默认对应的表单控件是一个TextInput. 在管理员站点添加了一个JavaScript写的日历控件,和一个“Today"的快捷按钮,包含了一个额外的invalid_date错误消息键
④auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果
TimeField: 使用Python的datetime.time实例表示的时间,参数同DateField
DateTimeField: 使用Python的datetime.datetime实例表示的日期和时间,参数同DateField
FileField: 一个上传文件的字段
ImageField: 继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image

字段选项:

通过字段选项,可以实现对字段的约束
在字段对象时通过关键字参数指定
null:如果为True,Django 将空值以NULL 存储到数据库中,默认值是 False
blank:如果为True,则该字段允许为空白,默认值是 False
对比:null是数据库范畴的概念,blank是表单验证证范畴的
db_column:字段的名称,如果未指定,则使用属性的名称
db_index:若值为 True, 则在表中会为此字段创建索引
default:默认值
primary_key:若为 True, 则该字段会成为模型的主键字段
unique:如果为 True, 这个字段在表中必须有唯一值

3.2.3增删改查

1.增加操作

from myapp.models import Users

ob = Users() 	# 实例化一个新的对象(空对象)
ob.name = '张三'
ob.age = 22
ob.phone = '15533700012'
ob.save()		# 新对象是添加,以存在对象是修改

2.删除操作

# 删除操作
mod = Users.objects     # 获取users的model对象
user = mod.get(id=6)    # 获取id为6的数据信息
user.delete()           # 执行删除操作

3.修改操作

ob = Users.objects.get(id=3)
ob.name = "小刘"
ob.age = 22
ob.save()		# 新对象是添加,以存在对象是修改

4.数据查询

all()
filter()
exclude()
order_by()
values():一个对象构成一个字典,然后构成一个列表返回

举例:

filter(键1=值1,键2=值2)
等价于
filter(键1=值1).filter(键2=值2)

返回单个值的方法

get():返回单个满足条件的对象
如果未找到会引发"模型类.DoesNotExist"异常
如果多条被返回,会引发"模型类.MultipleObjectsReturned"异常
count():返回当前查询的总条数
first():返回第一个对象
last():返回最后一个对象
exists():判断查询集中是否有数据,如果有则返回True

查询代码演示:

mod = Users.objects
# 1.所有
ulist = mod.all()
for u in ulist:
	print(u)
# 2.过滤
u = mod.filter(name='小刘')   # 获取name为小刘的信息
u = mod.filter(age__gt=20)    # 获取age大于20的信息
u = mod.filter(age__gte=20)    # 获取age大于等于20的信息
print(u)
# 3.排序
ulist = mod.order_by('age')
for u in ulist:
	print(u)
# 4 切片数据
ulist = mod.order_by('age')[:2]
for u in ulist:
	print(u)
# 5.使用sql语句查询
Users.objects.raw('sql 语句')

3.3 Django的视图层

3.3.1 视图返回

  • 1.这是一个返回当前日期和时间的视图,作为HTML文档:
from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)
  • 2.返回错误
# 直接返回一个404,没有去加载404的模板页面
return HttpResponseNotFound('<h1>Page not found</h1>')

# 可以直接返回一个status状态码
return HttpResponse(status=403)

# 返回一个404的错误页面
raise Http404("Poll does not exist")
  • 3.重定向
from django.shortcuts import redirect
from django.urls import reverse

# redirect重定向  reverse反向解析url地址
return redirect(reverse('userindex'))

# 执行一段js代码,用js进行重定向
return HttpResponse('<script>alert("添加成功");location.href = "/userindex"; </script>')

# 加载一个提醒信息的跳转页面
context = {'info':'数据添加成功','u':'/userindex'}
return render(request,'info.html',context)
  • 4.基于类的基本视图

views.py文件:

from django.http import HttpResponse
from django.views import View

class MyView(View):
	def get(self, request, *args, **kwargs):
		return HttpResponse('Hello, World!')

urls.py文件:

from django.urls import path
from myapp.views import MyView

urlpatterns = [
    path('mine/', MyView.as_view(), name='my-view'),
]

3.3.2 HttpResponse对象

1.在django.http模块中定义了HttpResponse对象的API。
2.HttpRequest对象由Django自动创建,HttpResponse对象由程序员创建。
3.在每一个视图函数中必须返回一个HttpResponse对象,当然也可以是HttpResponse子对象。

  • 1.直接返回数据
from django.http import HttpResponse

def index(request):
    return HttpResponse('你好')
  • 2.调用模板返回数据
from django.http import render

def index(request):
	# 返回模板
	return render(request,'user/edit.html',{'info':'你好'})
  • 3.子类HttpResponseRedirect 重定向
from django.shortcuts import redirect
from django.urls import reverse

def index(request):
    return redirect(reverse('myindex')
  • 4.子类JsonResponse

返回json数据,一般用于异步请求
帮助用户创建JSON编码的响应
JsonResponse的默认Content-Type为application/json

from django.http import JsonResponse

def index2(requeset):
	# 注意:参数类型是字典,如果是数组,需要先转成字典
    return JsonResponse({'list': 'abc'})
  • 5.关于cookie

设置cookie

 # 获取当前的 响应对象
 response = HttpResponse('cookie的设置')

 # 使用响应对象进行cookie的设置
 response.set_cookie('a','abc')

 # 返回响应对象
 return response

获取cookie

# 读取
a = request.COOKIES.get('a',None)

if a:
    return HttpResponse('cookie的读取:'+a)
else:
    return HttpResponse('cookie不存在')

3.3.3 HttpReqeust对象

服务器接收到http协议的请求后,会根据报文创建HttpRequest对象
视图函数的第一个参数是HttpRequest对象
在django.http模块中定义了HttpRequest对象的API

  • 1.属性(除特殊说明,属性都是只读的)

path: 一个字符串,表示请求的页面的完整路径,不包含域名
method: 一个字符串,表示请求使用的HTTP方法,常用值包括:‘GET’、‘POST’
encoding: 一个字符串,表示提交的数据的编码方式
-----如果为None则表示使用浏览器的默认设置,一般为utf-8
-----这个属性是 可写的 ,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值
GET: 一个类似于字典的对象,包含get请求方式的所有参数
POST: 一个类似于字典的对象,包含post请求方式的所有参数
FILES: 一个类似于字典的对象,包含所有的上传文件
COOKIES: 一个标准的Python字典,包含所有的cookie,键和值都为字符串
session: 一个既可读又可写的类似于字典的对象,表示当前的会话,只有当Django 启用会话的支持时才可用,详细内容见“状态保持”

  • 2.方法

is_ajax():如果请求是通过XMLHttpRequest发起的,则返回True

3.4 Django模板层

3.4.1模板引擎配置

模板引擎使用该TEMPLATES设置进行配置。这是一个配置列表,每个引擎一个。
默认值为空。在 settings.py由所产生的startproject命令定义一个更有用的值:
在做下面模板配置的同时,也要在项目的根目录下创建一个templates目录

settings.py文件中进行配置:

TEMPLATES = [
	{
	   'BACKEND': 'django.template.backends.django.DjangoTemplates',
	   # 指定模板根目录
	   'DIRS': [os.path.join(BASE_DIR,'templates')],
	   'APP_DIRS': True,
	   'OPTIONS': {
	       'context_processors': [
	           'django.template.context_processors.debug',
	           'django.template.context_processors.request',
	           'django.contrib.auth.context_processors.auth',
	           'django.contrib.messages.context_processors.messages',
	       ],
	   },
	},
]

在应用的视图文件加载模板,并放置要输出的数据

return render(request,“目录/模板文件.html”,{放置字典数据})

3.4.2 模板语法

  • 1.变量
{{  var  }}

当模版引擎遇到点(“.”),会按照下列顺序查询:
字典查询,例如:foo[“bar”]
属性或方法查询,例如:foo.bar
数字索引查询,例如:foo[bar]

  • 2.标签

语法:

{%  tag  %}

作用:
在输出中创建文本
控制循环或逻辑
加载外部信息到模板中

① for标签

{%  for ... in ...  %}
    循环逻辑
{%  endfor  %}

② if标签

{%  if ...  %}
    逻辑1
{%  elif ...  %}
    逻辑2
{%  else  %}
    逻辑3
{%  endif  %}

③ comment标签

{%  comment  %}
    多行注释
{%  endcomment  %}

④ include:加载模板并以标签内的参数渲染

{%  include "base/index.html"  %}

⑤ url:反向解析

{%  url 'name' p1 p2  %}

⑥ csrf_token:这个标签用于跨站请求伪造保护

{%  csrf_token  %}
  • 3.过滤器

语法:(使用管道符号 "|"来应用过滤器)

{{ 变量|过滤器 }},例如{{ name|lower }},表示将变量name的值变为小写输出

举例:

# 1.关闭HTML自动转义
{{ data|safe }}
# 2.可以在if标签中使用过滤器结合运算符
if list1|length > 1
# 3.过滤器能够被“串联”,构成过滤器链
{{ name|lower|upper }}
# 4.过滤器可以传递参数,参数使用引号包起来
{{ list|join:", " }}
# 5.default:如果一个变量没有被提供,或者值为false或空,则使用默认值,否则使用变量的值
{{ value|default:"什么也没有" }}
# 6.date:根据给定格式对一个date变量格式化
{{ value|date:'Y-m-d' }}

官方文档内置过滤器参考:
网址:https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/#ref-templates-builtins-filters

  • 4.注释

单行注释

{# 注释 #}

多行注释

{%  comment  %}
      多行注释
{%  endcomment  %}
  • 5.模板运算

加:

{{  value|add:10  }}
note:value=5,则结果返回15

减:

{{  value|add:-10  }}
note:value=5,则结果返回-5,加一个负数就是减法了

乘:

{%  widthratio 5 1 100  %}
note:等同于:(5 / 1) * 100 ,结果返回500,
withratio需要三个参数,它会使用参数1/参数2*参数3的方式进行运算,进行乘法运算,使「参数2=1

除:

{%  widthratio 5 100 1  %}
note:等同于:(5 / 100) * 1,则结果返回0.05,和乘法一样,使「参数3= 1就是除法了。

4.常用web工具

4.1文件上传

当Django在处理文件上传的时候,文件数据被保存在request.FILES
FILES中的每个键为<input type=“file” name=“ ”/>中的name
注意:FILES只有在请求的方法为POST 且提交的带有enctype=“multipart/form-data” 的情况下才会包含数据。
否则,FILES 将为一个空的类似于字典的对象

前端代码:

<html>
<head>
    <title>文件上传</title>
</head>
<body>
    <form method="post" action="upload/" enctype="multipart/form-data">
        <input type="text" name="title"><br>
        <input type="file" name="pic"/><br>
        <input type="submit" value="上传">
    </form>
</body>
</html>

后台处理:

from django.shortcuts import render
from django.http import HttpResponse
from PIL import Image
import time,os

def upload(request):
    '''执行图片的上传'''
    myfile = request.FILES.get("mypic",None)
    if not myfile:
        return HttpResponse("没有上传文件信息")
    filename = str(time.time())+"."+myfile.name.split('.').pop()
    destination = open("./static/pics/"+filename,"wb+")
    for chunk in myfile.chunks():      # 分块写入文件  
        destination.write(chunk)  
    destination.close()

    # 执行图片缩放
    im = Image.open("./static/pics/"+filename)
    # 缩放到75*75(缩放后的宽高比例不变):
    im.thumbnail((75, 75))
    # 把缩放后的图像用jpeg格式保存: 
    im.save("./static/pics/s_"+filename,None)

    #执行图片删除
    #os.remove("./static/pics/"+filename)

    return HttpResponse("上传成功!图片:"+filename)

4.2分页操作

4.2.1 Paginator对象:

Paginator(列表,int):返回分页对象,参数为列表数据,每面数据的条数

属性:

count:对象总数
num_pages:页面总数
page_range:页码列表,从1开始,例如[1, 2, 3, 4]

方法:

page(num):下标以1开始,如果提供的页码不存在,抛出InvalidPage异常

异常exception:

InvalidPage:当向page()传入一个无效的页码时抛出
PageNotAnInteger:当向page()传入一个不是整数的值时抛出
EmptyPage:当向page()提供一个有效值,但是那个页面上没有任何对象时抛出

4.2.2 Page对象

Paginator对象的page()方法返回Page对象,不需要手动构造

属性:

object_list:当前页上所有对象的列表
number:当前页的序号,从1开始
paginator:当前page对象相关的Paginator对象

方法:

has_next():如果有下一页返回True
has_previous():如果有上一页返回True
has_other_pages():如果有上一页或下一页返回True
next_page_number():返回下一页的页码,如果下一页不存在,抛出InvalidPage异常
previous_page_number():返回上一页的页码,如果上一页不存在,抛出InvalidPage异常
len():返回当前页面对象的个数
迭代页面对象:访问当前页面中的每个对象

代码样例:

from django.core.paginator import Paginator

def pagTest(request, pIndex):
    list1 = Users.objects.filter(xxx)
    p = Paginator(list1, 10)
    if pIndex == '':
        pIndex = '1'
    pIndex = int(pIndex)
    list2 = p.page(pIndex)
    plist = p.page_range
    return render(request, 'booktest/pagTest.html', {'list': list2, 'plist': plist, 'pIndex': pIndex})

5.其他功能

5.1静态文件

配置静态文件,在myweb/settings.py文件中:

# 访问时的地址
STATIC_URL = '/static/'
# 配置静态文件的路径
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

网页访问(举例):

http://localhost:8000/static/mypics/lala.jpg

模板使用:

<!-- 第一行这个得写,先引入才能使用 -->
{ % load static from staticfiles % }
<img src="{ % static "my_app/myexample.jpg" % }" alt="My image"/>

5.2 CSRF

CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本XSS,但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性
CSRF中间件和模板标签为防止跨站点请求伪造提供了易用的保护。
当恶意网站包含链接,表单按钮或某些旨在在您的网站上执行某些操作的JavaScript时,会使用在浏览器中访问恶意网站的登录用户的凭据进行此类攻击。
还介绍了一种相关攻击类型,即“登录CSRF”,攻击网站欺骗用户的浏览器,以便使用其他人的凭证登录到网站。

1.CSRF的使用:

  • step1:在settings.py中启用’django.middleware.csrf.CsrfViewMiddleware’中间件,此项在创建项目时,默认被启用
  • step2:在HTML的表单中添加标签
<form>
{ % csrf_token % }
...
</form>

2.取消保护
如果某些视图不需要保护,可以使用装饰器csrf_exempt,模板中也不需要写标签,修改csrf2的视图如下:

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt 
def csrf2(request):
    uname=request.POST['uname'] 
    return render(request,'booktest/csrf2.html',{'uname':uname}) 
    运行上面的两个请求,发现都可以请求

5.3 状态保持

1.开启session

使用django-admin startproject创建的项目默认启用
禁用会话:删除下面指定的两个值,禁用会话将节省一些性能消耗
Django 中session需要依赖数据库,因此需要确认数据库中是否存在 与session相关的 表

在settings.py文件中

* 项INSTALLED_APPS列表中添加:
* 'django.contrib.sessions',

* 项MIDDLEWARE_CLASSES列表中添加:
* 'django.contrib.sessions.middleware.SessionMiddleware',

2.使用session

启用会话后,每个HttpRequest对象将具有一个session属性,它是一个类字典对象
get(key, default=None):根据键获取会话的值
clear():清除所有会话
flush():删除当前的会话数据并删除会话的Cookie
del request.session[‘member_id’]:删除会话

示例:

#session设置
 request.session[key] = value

#session获取
 request.session.get(key,default=Node)

#session删除

# 删除单个key 不存在时报错
 del request.session['a'] 

#清除所有会话,但不会删除数据
 request.session.clear() 

#删除当前的会话数据
 request.session.flush()

5.4 中间件

中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出
激活:添加到Django配置文件中的MIDDLEWARE_CLASSES元组中
使用中间件,可以干扰整个处理过程,每次请求中都会执行中间件的这个方法

举例:验证用户是否登陆示例

  • 1.在应用中创建AdminLoginMiddleware.py文件
from django.shortcuts import render
from django.http import HttpResponse
import re

class AdminLoginMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):


        # 检测当前的请求是否已经登录,如果已经登录,.则放行,如果未登录,则跳转到登录页
        # 获取当前用户的请求路径  /admin/开头  但不是 /admin/login/  /admin/dologin/   /admin/verifycode
        urllist = ['/admin/login','/admin/dologin','/admin/vcode']
        # 判断是否进入了后台,并且不是进入登录页面
        if re.match('/admin/',request.path) and request.path not in urllist:

            # 检测session中是否存在 adminlogin的数据记录
            if request.session.get('Vuser','') == '':
                # 如果在session没有记录,则证明没有登录,跳转到登录页面
                # return HttpResponse('<script>alert("请先登录");location.href="/admin/login";</script>')
				return redirect(reverse("login"))


		# 放行,继续往下走
        response = self.get_response(request)
        return response
  • 2.配置中间件

在settings.py文件中修改MIDDLEWARE_CLASSES选项

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    #自定义的中间件
    'myadmin.AdminMiddleware.AdminLoginMiddleware'
]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值