1.前期准备
1.1相关链接
Django官网:https://www.djangoproject.com/ Django中文文档参考网站:https://yiyibooks.cn django与python版本的对应关系:
Django version | Python version |
---|
2.2 | 3.5,3.6,3.7,3.8(added in 2.2.8) | 3.0,3.1,3.2 | 3.6,3.7,3.8 |
1.2Django安装
在线安装:
pip install django==2.2.*
python -m django --version
1.3创建项目、启动、创建应用
django-admin startproject 项目名
python manage.py runserver
python manage.py runserver 9000
python manage.py runserver 0.0.0.0:9000
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('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
class Stu(models.Model):
'''自定义Stu表对应的Model类'''
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)
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',
]
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传参示例
urlpatterns = [
path('', views.index),
path('add/', views.add),
path('add/<int:sid>', views.add),
path('add/<int:sid>/<str:name>', views.add),
]
def add(request, sid=0, name=''):
result = "add." + str(sid) + " " + name
return HttpResponse(result)
注意:
要从URL捕获一个值,请使用 尖括号 括起来。 捕获的值可以选择包括转换器类型。例如,用于<int:name>捕获整数参数。如果不包括转换器/,则匹配除字符以外的任何字符串。 无需添加斜杠,因为每个URL都有该斜杠。例如articles,不是/articles。
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),
]
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')
reverse('add2',args=(sid,name))
reverse('add2',args=(100,'李四'))
return redirect(reverse('add2',args=(sid,name)))
3.2Django的模型层
3.2.1迁移文件生成与迁移
一般不用,一般是先创建数据库,然后使用。 首先按照框架初始章节,对数据库进行连接。如果数据库中没有表,可以在myapp/models.py文件中进行编写,然后生成迁移文件并执行迁移。这个时候数据库中也会增加数据库表。
python manage.py makemigrations
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
user = mod.get(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
ulist = mod.all()
for u in ulist:
print(u)
u = mod.filter(name='小刘')
u = mod.filter(age__gt=20)
u = mod.filter(age__gte=20)
print(u)
ulist = mod.order_by('age')
for u in ulist:
print(u)
ulist = mod.order_by('age')[:2]
for u in ulist:
print(u)
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)
return HttpResponseNotFound('<h1>Page not found</h1>')
return HttpResponse(status=403)
raise Http404("Poll does not exist")
from django.shortcuts import redirect
from django.urls import reverse
return redirect(reverse('userindex'))
return HttpResponse('<script>alert("添加成功");location.href = "/userindex"; </script>')
context = {'info':'数据添加成功','u':'/userindex'}
return render(request,'info.html',context)
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子对象。
from django.http import HttpResponse
def index(request):
return HttpResponse('你好')
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')
返回json数据,一般用于异步请求 帮助用户创建JSON编码的响应 JsonResponse的默认Content-Type为application/json
from django.http import JsonResponse
def index2(requeset):
return JsonResponse({'list': 'abc'})
设置cookie
response = HttpResponse('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
path: 一个字符串,表示请求的页面的完整路径,不包含域名 method: 一个字符串,表示请求使用的HTTP方法,常用值包括:‘GET’、‘POST’ encoding: 一个字符串,表示提交的数据的编码方式 -----如果为None则表示使用浏览器的默认设置,一般为utf-8 -----这个属性是 可写的 ,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值 GET: 一个类似于字典的对象,包含get请求方式的所有参数 POST: 一个类似于字典的对象,包含post请求方式的所有参数 FILES: 一个类似于字典的对象,包含所有的上传文件 COOKIES: 一个标准的Python字典,包含所有的cookie,键和值都为字符串 session: 一个既可读又可写的类似于字典的对象,表示当前的会话,只有当Django 启用会话的支持时才可用,详细内容见“状态保持”
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 模板语法
{{ var }}
当模版引擎遇到点(“.”),会按照下列顺序查询: 字典查询,例如:foo[“bar”] 属性或方法查询,例如:foo.bar 数字索引查询,例如:foo[bar]
语法:
{% 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 %}
语法:(使用管道符号 "|"来应用过滤器)
{{ 变量|过滤器 }},例如{{ name|lower }},表示将变量name的值变为小写输出
举例:
{{ data|safe }}
if list1|length > 1
{{ name|lower|upper }}
{{ list|join:", " }}
{{ value|default:"什么也没有" }}
{{ value|date:'Y-m-d' }}
官方文档内置过滤器参考: 网址:https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/#ref-templates-builtins-filters
单行注释
{
多行注释
{% comment %}
多行注释
{% endcomment %}
加:
{{ 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)
im.thumbnail((75, 75))
im.save("./static/pics/s_"+filename,None)
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’]:删除会话
示例:
request.session[key] = value
request.session.get(key,default=Node)
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
def __call__(self, request):
urllist = ['/admin/login','/admin/dologin','/admin/vcode']
if re.match('/admin/',request.path) and request.path not in urllist:
if request.session.get('Vuser','') == '':
return redirect(reverse("login"))
response = self.get_response(request)
return response
在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'
]
|