Django 的主要目的是简便、快速的开发数据库驱动的网站。
Django 是一款重量级框架, 内部架构使用的是 MVT 设计模式。
其核心思想是分工, 解耦,让不同的代码块之间降低耦合,
增强代码的可扩展性和可移植性,实现向后兼容。
MVC框架
MVT框架
一、安装Virtualenv
• 1、打开 CMD命令行
• 2、pip安装模块
pip install virtualenv
# 豆瓣加速
pip install virtualenv -i https://pypi.douban.com/simple/
二、安装 VirtualenvWrapper-win
1、安装virtualenvWrapper-win
pip install virtualenvwrapper-win -i https://pypi.douban.com/simple/
2、设置虚拟环境目录
需要在windows中配置WORKON_HOME路径:
3、确定以后,重启CMD
4、创建虚拟环境
mac/unbantu不需要配置
mkvirtualenv : 创建一个新的虚拟环境。
django_env : 创建的新虚拟环境名称, 这个名称可以随意制定。
-p : 制定使用的python解释器版本。
python3 : 我们这里使用 python3 的解释器。
pip : python 包管理器
install : 安装
django== 1.11.11
mkvirtualenv django_env -p python3
pip install django==1.11.11
其他补充命令
# 虚拟环境
mkvirtualenv # 创建虚拟环境
rmvirtualenv # 删除虚拟环境
workon # 进入虚拟环境、查看所有虚拟环境
deactivate # 退出虚拟环境
# pip
pip install # 安装依赖包
pip uninstall # 卸载依赖包
pip list # 查看已安装的依赖库
django-admin : django 生成项目工程的命令
startproject : 快速创建一个 django 项目, 使用这个命令可以快速下载一个项目模板, 在我们所在的目录
工程名称 : 项目名称, 可以随意定义
# 生成一个 django 项目工程的使用方式:
#django-admin startproject 工程名称
# 调用 django 项目生成命令,生成项目:
django-admin startproject demo
# 调用如下命令, 就可以使我们的项目运行起来
# 默认运行在 127.0.0.1:8000 的 IP 和 端口上:
python manage.py runserver
1.若报错报错原因以及解决方法:
使用命令行创建的项目, 而不是使用 pycharm 创建的, 所以当前项目中的 python 解析器没有对应到虚拟环境 ( django_py3_1.11 ) 中的 python 版本上, 故报错。可以在 pycharm 的命令行中看出: 命令行前面没有显示当前虚拟环境名称: ( django_py3_1.11 )。
切换当前 pycharm 项目的 python 解析器。
2.在 manage.py 中点击右键, 启动一次。
然后选择右上角的编辑按钮, 在 manage.py 命令Parameters后面添加 runserver 参数。再次运行。
生成的子应用中各个文件的作用:
admin.py 文件跟网站的后台管理站点配置相关。
apps.py 文件用于配置当前子应用的相关信息。
migrations 目录用于存放数据库迁移历史文件。
models.py 文件用户保存数据库模型类。
tests.py 文件用于开发测试用例,编写单元测试。
views.py 文件用于编写Web应用视图。
# 创建子应用的常见命令:
python manage.py startapp 子应用名称
# 执行生成子应用的指令, 生成一个叫users的子应用:
python manage.py startapp users
配置子应用
settings 中默认的配置信息
settings 文件里, 找到installed_apps 列表:
将刚创建的 users 子应用中 apps.py 文件的信息
[‘users.apps.UsersConfig’, ], 添加到 INSTALLED_APPS 中。
格式:子应用名.apps.类名
在 views.py 中编写视图代码
光标在函数上,alt+回车,自动补全导入包。
# 从 django.http 模块中导入 HttpRespose
from django.http import HttpResponse
#def 函数名(request):
def index(request): #request不可缺少
return HttpResponse("hello the world!") # HttpResponse
在工程总路由 demo / urls.py 中添加子应用的路由数据。(一个子应用,在总路由中只添加一次)
# 导入:
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls), # django默认就有的路由配置信息
# 额外添加如下的路由配置信息:
url(r'^users/', include('users.urls')),
# url(r'^users/', include(users.urls)), # include 函数除了可以传递字符串之外,也可以直接传递应用的 urls 块
]
在子应用中新建一个 urls.py 文件
在 子应用users / urls.py 文件中定义路由信息
(子应用,增加一个views.py函数,子路由中就添加一次。总路由不需改变。)
# 从 urls 模块中导入 url
from django.conf.urls import url
# 从当前目录导入我们的视图模块 views
from . import views
# urlpatterns 是被 django 自动识别的路由列表变量
urlpatterns = [
# 每个路由信息都需要使用 url 函数来构造
# url (路径, 视图) 前面用于正则匹配
url(r'^index/$', views.index),
]
之后在views.py中添加新函数,在子应用users / urls.py中添加新的路由信息。
settings.py 是整个项目的配置文件.
BASE_DIR 指的是项目的绝对路径
一般在开发时, 都会使用 DEBUG 模式, 默认为 True (开启)。
http:// 代表使用的协议
www.taobao.com 指的是访问的域名
80 指的是调用的端口
/users/index/ 指的是路由部分
?a=1&b=2&c=3 指的是查询字符串
#box 指的是锚点
路由解析顺序:Django 在接收到一个请求时,从主路由文件中的 urlpatterns 列表中以由上至下的顺序查找对应路由规则,如果发现规则为 include 包含,则再进入被包含的 urls 中的 urlpatterns 列表由上至下进行查询。
注意定义路由的顺序,避免出现屏蔽效应。
urlpatterns = [
url(r'^say', views.say),
url(r'^sayhello', views.sayhello),
] #不会执行sayhello,执行到路由say,即执行say函数。
#1. 调整书写顺序
from django.conf.urls import url
from . import views
urlpatterns = [
# 1. 调整书写顺序
url(r'^sayhello', views.sayhello),
url(r'^say', views.say)
]
# 2.调整正则书写方式:
from django.conf.urls import url
from . import views
urlpatterns = [
# 2.调整正则:
url(r'^say/$', views.say),
url(r'^sayhello/$', views.sayhello)
]
给总路由添加命名: include(‘子应用.urls’, namespace=“名称” )
给子路由添加命名: url(‘正则’, 视图函数, name=“名称”)
#主路由命名
url(r'^users/', include('users.urls', namespace='users')),
#子路由命名
urlpatterns = [
url(r'^index/$', views.index, name='index'),
url(r'^say', views.say, name='say'),
]
使用 reverse 函数,可以根据路由名称,返回具体的路径。
reverse 函数的主要作用是:
在视图中获取某一个视图函数的完整路由。
reverse 完成用法: reverse( ‘总路由名称 : 子路由名称’ )
reverse 函数的另一种用法: reverse( ‘子路由名称’ )
def change(request):
#对于指明 namespace 的
#reverse ( 命名空间 namespace : 路由name )
path = reverse('kids:say')
#重定向,用于跳转另一个网页
return redirect(path)
路径中的 / 代表路径分隔符, 一般我们发请求时最好携带.
如果发请求时, 没有在最后携带 / , 则浏览器会帮我们进行一次重定向, 再次访问携带 / 的路径。【postman测试不能自动添加/】
QueryDict 对象是 django 中一种特殊类型的字典。
里面可以存储 一对一类型的数据, 也可以存储 一对多类型的数据。
如果获取一个值: QueryDict.get( key ) 获取的是所有值的最后一个。
如果获取多个值: QueryDict.getlist( key ) 获取这个键对应的所有值, 存放在列表中返回。
# 子路由添加
url(r"^Qstring",views.Qstring),
#查询字符串传参 ?a=1&b=2&a=3
#http://127.0.0.1:8000/kid/Qstring/?a=1&b=2&a=3
def Qstring(request):
# Querydict=request.GET
# a=Querydict.get("a")
a=request.GET.get('a')
b=request.GET.get('b')
list=request.GET.getlist('a')
print(a)
print(b)
print(list)
return HttpResponse("查询字符串传参")
#子路由添加
url(r"^url/([a-z]+)(\d{4}/$)", views.urlpath),
url(r"^durl/(?P[a-z]+)(?P\d{3}/$)" , views.Durlpath), #命名参数
#URL 路径传参,正则分组,自动传参
# http://127.0.0.1:8000/kid/url/shandong2020/
#未命名
def urlpath(request,city,year):
print(city)
print(year)
return HttpResponse("路径传参成功")
# 命名参数
def Durlpath(request,name,number):
print(name)
print(number)
return HttpResponse("命名参数路径传参成功")
Django 默认开启了 CSRF 防护,会对上述请求方式进行 CSRF 防护验证,在测试时可以关闭 CSRF 防护机制,方法为在 settings.py 文件中注释掉 CSRF 中间件。
#子路由添加
url(r"^bodyform/$",views.bodyform),
#请求体传参,表单类型,JSON
#注:GET无请求体,GET表单请求即为查询字符串传参。
def bodyform(request):
# QueryDict=request.POST
# name=QueryDict.get("username")
#可用自己写的表单提交,也可用postman发送字典
name=request.POST.get("username")
pwd=request.POST.get("pwd")
sex=request.POST.get("sex")
city=request.POST.get("city")
print(name,pwd,sex,city)
return HttpResponse("表单post类型传参成功")
#子路由添加
url(r"^bodyjson/$",views.bodyjson),
#JSON传参#请求体传参,表单类型,JSON
def bodyjson(request):
json_byte=request.body
str=json_byte.decode() #二进制转化为字符串
dict=json.loads(str)#转化为字典
# dict=json.loads(request.body.decode())
a=dict.get("a")
b=dict.get("b")
print(a)
print(b)
#postman发送json格式:post->raw->json
return HttpResponse("json类型传参成功")
通过 request.META 属性获取请求头中的数据 request.META 为字典类型。(行、头、空行、体)
POST /reqresp/req/ HTTP/1.1 #请求行
Host: 127.0.0.1:8000 #请求头
Content-Type: application/x-www-form-urlencoded #请求头
Cache-Control: no-cache #请求头
Postman-Token: dd531a45-7518-1e8f-63a5-be03ed593471 #请求头
#空行
a=1&b=2&a=3 #请求体
请求头,可以看成字典格式。
其他信息
method:一个字符串,表示请求使用的 HTTP 方法,常用值包括:‘GET’、‘POST’。
user:请求的用户对象。
path:一个字符串,表示请求的页面的完整路径,不包含域名和参数部分。
encoding:一个字符串,表示提交的数据的编码方式。
def headers(request):
print(request.META.get('CONTENT_TYPE'))
print(request.META['CONTENT_LENGTH'])
print(request.method)
print(request.users)
print(request.path)
return HttpResponse("已获得请求头的信息")
定义格式:
HttpResponse(
content=响应体,
content_type=响应体数据类型,
status=状态码
)
#子路由添加
url(r"^resp/$",views.resp),
# 响应 content:表示返回的内容。
# status_code:返回的 HTTP 响应状态码。
# content_type:指定返回数据的的 MIME 类型。
def resp(request):
# alt+回车,补全函数。
return HttpResponse('{"name": "python"}',
content_type="application/json", #类型名要么默认,要么符合返回的类型
status=500) #100-599
HttpResponse 的子类
子类有:
HttpResponseRedirect 301
HttpResponsePermanentRedirect 302
HttpResponseNotModified 304
HttpResponseBadRequest 400
HttpResponseNotFound 404
HttpResponseForbidden 403
HttpResponseNotAllowed 405
HttpResponseGone 410
HttpResponseServerError 500
def notfund(request):
return HttpResponseNotFound("not found")
JsonResponse
#子路由添加
url(r"^json/$",views.json),
# 导入 JsonResponse
from django.http import JsonResponse
def json(request):
return JsonResponse({"name":"xaiowang","age":18})
由服务端生成, 保存在客户端的一种数据存储形式, 内部以 key/value 键值对形式存储. 一般不存储敏感信息. 内容有时会被加密.状态保持
Cookie 以键值对 Key-Value 形势进行信息的存储,基于域名安全,不同域名的 Cookie 是不能互相访问的。
cookie 的设置: response.set_cookie( key, value, max_age=时间(s))
cookie 的获取: request.COOKIES.get( key )
#子路由添加
url(r'^setcook/$',views.setcookies),
url(r'^getcook/$',views.getcookies),
#views.py中添加
def setcookies(request):
print("setcookie")
response=HttpResponse("设置cookie")
# response.set_cookie('key','value',max_age="")
response.set_cookie('key1','value1',max_age=14*24*3600)
return response
def getcookies(request):
dict=request.COOKIES
value=dict.get("key1")
print(value)
return HttpResponse("读取 Cookie")
Session 是一种会话控制方式. 由服务端创建, 并且保存在服务端的数据存储形式. 内部以 key/value 键值对的形式存储. 可以存储敏感信息, 内容有些会被加密. 一般生成 session 后,会把 sessionid 传递给 cookie 保存. 依赖 cookies。
settings.py 文件中,可以设置 session 数据的存储方式,可以保存在数据库、本地缓存等。我们一般用redis保存session。
在 redis 中保存 session,需要引入第三方扩展django-redis 。
1) 安装扩展
记住在虚拟环境中安装!
pip install django-redis
2)配置
在 settings.py 文件中做如下设置。直接复制在最后。
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1", #redis一共十六个数据库,这是选择第一个。
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"
#子路由添加
url(r'^setse/$',views.setsession),
url(r'^getse/$',views.getsession),
#views.py添加
def setsession(request):
request.session['key1']='value1'
#创建session写入key/value,生成sessionid放入cookie,
# cookie发给前端。(此步生成新的cookie)
return HttpResponse("session设置成功")
def getsession(request):
value=request.session['key1']
print(value)
return HttpResponse("session读取成功")
共同点:都是缓存,用于状态保持。
不同点:cookie有大小限制4k,不安全,保存在浏览器。
session无大小限制,安全,保存在服务器。
在 Django 中, 以函数的方式定义的视图称为函数视图, 也可以使用类来定义一个视图,称为类视图。
使用类视图可以将视图对应的不同请求方式以类中的不同方法来区别定义。代码可读性好,类视图相对于函数视图有更高的复用性。
#子路由
url(r'^classapp/$',views.ClassView.as_view()),
#注意 : 配置子路由时,类名后面需要增加 as_view( ) 函数。
#views
class ClassView(View): #类名大驼峰定义,object换成View,注意大写
#alt+回车 自动导包
def get(self,request): #必须小写,函数名不能修改。
print("得到get")
return HttpResponse('get请求')
def post(self,request): #csrf关闭->setting middleware设置
print("得到post")
return HttpResponse("post请求")
def put(self,request):
print("得到put")
return HttpResponse("put请求")
as_view( ) 这个函数中会判断前端的请求方法在类视图中是否有添加。有, 则直接访问该函数;没有, 则会报找不到的错误 ( 405 )。
#子路由
url(r'mixinview/$',views.MixinView.as_view()),
#views代码
from django.http import HttpResponse
from django.shortcuts import render
from django.views import View
def my_decorator1(func): #自定义装饰器1
def wrapper(request,*args,**kwargs):
print('自定义装饰器1被调用')
print('请求路径1%s'%request.path)
return func(request,*args,**kwargs)
return wrapper
def my_decorator2(func): #自定义装饰器2
def wrapper(request,*args,**kwargs):
print('自定义装饰器2被调用')
print('请求路径2%s'%request.path)
return func(request,*args,**kwargs)
return wrapper
class FirstMixin(object): #FirstMixin 扩展类
@classmethod
def as_view(cls,*args,**kwargs):
view=super().as_view(*args,**kwargs) #在 Mixin 扩展类中, 我们一般会重写 as_view( ) 函数. 在函数内添加过滤
view=my_decorator1(view)
return view
class SecondMixin(object):
@classmethod
def as_view(cls,*args,**kwargs):
view=super().as_view(*args,**kwargs)
view=my_decorator2(view)
return view
class MinxinView(FirstMixin,SecondMixin,View): #类视图调用时, 需要把 View 类添加到最后
def get(self,request):
print("get方法")
return HttpResponse("get方法")
def post(self,request):
print("post方法")
return HttpResponse("post方法")