Django 学习之路
一、Django项目创建
1.项目结构
1.1. settings.py 文件
"""
Django settings for mydemo project.
Generated by 'django-admin startproject' using Django 3.1.7.《django版本》
For more information on this file, see
https://docs.djangoproject.com/en/3.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.1/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent """《显示当前项目根目录》"""
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'jb^(bip2g_@%r*5ni-8@#yz%*crzw7sqpq_qcbhw48lgk+ctxo'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
"""
调试模式开关,默认为True(调试模式)
为True时:1.检测代码改动后立刻重启服务;2.显示报错页面
为False时(正式启动模式/上线模式):项目上线时一定要更改为False
"""
ALLOWED_HOSTS = []
"""
允许的域名,只有列表中添加的域名可以访问服务器,默认会允许127.0.0.1或者localhost访问
设置为"*":表示允许所有域名访问
设置当前局域网内域名可进行访问:
1.项目启动时设置:python manage.py runserver 0.0.0.0:8000
2.添加局域网IP
"""
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
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',
]
ROOT_URLCONF = 'mydemo.urls'
"""
项目主路由位置,默认为项目文件夹下的urls.py
"""
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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',
],
},
},
]
"""
模版配置
"""
WSGI_APPLICATION = 'mydemo.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
"""
主页语言配置,可设置为中文
LANGUAGE_CODE = 'zh-hans'
"""
TIME_ZONE = 'UTC'
"""
时区设置,主要影响数据库时间显示
TIME_ZONE = 'Asia/shanghai'
"""
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
STATIC_URL = '/static/'
"""
静态文件路由
"""
1.2 URL
-
URL 结构:protocol://hostname[:port]/path[?query][#fragment]
- protocol(协议):
- http:通过http访问该资源,格式:http://
- https:通过安全的https:访问该资源,格式:https://
- file:通过file访问本地的资源,格式:file:///
- hostname(主机名/域名):
- 是指存放资源的服务器的域名系统(DNS)主机名、域名或IP地址
- port(端口):
- 可选,省略时使用方案的默认端口
- 各种传输协议都有默认的端口号http:默认是80,https:默认是443
- path(路由地址):
- 由零或多个“/”符号隔开的字符串,一般用来表示主机上的一个目录或文件地址,路由地址决定了服务器端如何处理这个请求
- query(查询字符串):
- 可选,以“?”开头,用于给动态网页传参,可传递多个参数用“&”隔开,参数名和参数值用等号隔开
key=value
- 可选,以“?”开头,用于给动态网页传参,可传递多个参数用“&”隔开,参数名和参数值用等号隔开
- fragment(信息片段):
- 字符串,以“#”开头,用于指定网络资源中的片段,类似书签,下次访问时带上fragment可直接定位到该片段
- protocol(协议):
-
Django如何处理URL请求
- 根据浏览器传过来的URL,django从配置文件中根据ROOT_URLCONF找到主路由文件;默认情况下该路由文件位于同名目录下的urls.py中
- django加载主路由中的urlpattern变量,urlpattern是一个包含很多路由的列表
- 从上往下依次匹配urlpattern中的path,匹配到第一个满足的path即中断后续匹配
- 匹配成功,调用对应的视图函数处理请求,返回对应的响应
- 匹配失败,返回404响应
1.3 视图函数
-
定义:用于接收浏览器请求( HttpRequest对象),并通过HttpResponse对象返回响应的函数
-
语法:return必须是HttpResponse对象
def demoview(request[,其他参数]): return HttpResponse('需要返回的数据')
-
示例:
在项目同名目录下创建views.pyfrom django.http import HttpResponse def page1_view(requet): html = "<h1>hallo world</h1>" return HttpResponse(html)
添加路由url.py
from django.contrib import admin from django.urls import path from . import views urlpatterns = [ path('admin/', admin.site.urls), path('page1/', views.page1_view), ]
1.4 路由配置-path
- path()函数
- 导入
from django.urls import path
- 语法
path(route,views,name=None)
- 参数:
- route:字符串类型,匹配的请求路径
- views:指定路径所对应的视图处理函数的名称
- name:为地址起别名,在模板中进行地址反向解析时使用
- path转换器
- 语法:<转换器类型:自定义名>
- 作用:若转换器类型匹配到对应类型的数据,则将数据按照关键字传参的方式传递给视图函数
- 例:
path('page/<int:page>',views.xxx)
,如果匹配到page路径后面时int类型,则会将接收到的路径中的数据赋值给变量page,然后以关键值传参的方式传递到视图中 -
转换器类型 作用 样例 str 匹配除了‘/’之外的非空字符串 ”v1/users/<str:username>“匹配/v1/users/china,匹配结果为:username=china
int 匹配0和任何正整数,返回一个int ”v1/users/<int:num>“匹配/v1/users/35,匹配结果为:num=35
slug 匹配任意有ASCII字母或数字以及连字符和下划线组成的短标签 ”v1/users/<slug:sl>“匹配/v1/users/this_is_django,匹配结果为:sl=this_is_django
path 匹配非空字段,包括路径分隔符”/“ ”v1/users/<path:ph>“匹配/v1/users/goods/a/b/c,匹配结果为:ph=goods/a/b/c
- re_path转换器
- 语法:
re_path(reg,view,name=xxx)
- 正则表达式必须为命名分组模式(
?P<name>pattern
;匹配成功后用关键字传参的方式传递给视图函数
- 正则表达式必须为命名分组模式(
- 作用:使用正则进行精确匹配
- 例:
url(r'^weather/(?P<city>[a-z]+)/(?P<year>\d{4})/$', views.weather),
- 语法:
二、请求与响应
2.1.请求和响应
2.1.1 django中的请求
- 视图函数中的第一个参数即为HttpRequest对象
- django接受到http协议的请求后,会根据请求数据报文创建HttpRequest对象
- HttpRequest对象通过属性,描述了请求的所有相关信息
-
HttpRequest属性:
属性名 说明 path_info URL字符串 method 字符串,表示Http请求方法:GET、POST、PUT等 GET QueryDict查询字典的对象,包含get请求方式的所有数据 POST QueryDict查询字典的对象,包含post请求方式的所有数据 FILES 类似于字典的对象,包含所有的上传文件信息 COOKIES python字典,包含所有的cookie,键和值都为字符串 session 类似于字典对象,表示当前的会话 body 字符串请求体的内容 scheme 请求协议(http或者https) request.get_full_path() 请求的完整路径,会将查询字符串一并取出 request.META 请求中的元数据(消息头) requset.META[‘REMOTE_ADDR’] 客户端IP地址
-
2.1.2 django中的响应对象
- 构造函数:
- HttpResponse(content=响应体,content_type=响应体数据类型,status=状态码)
- 作用:
- 向客户端浏览器返回响应,同时携带响应体类容
- 参数:
- content: 表示返回的内容
- status_code: 返回的HTTP响应状态码(默认为200)
- content_type: 指定返回数据的MIME类型(默认为text/html),浏览器会根据这个属性来显示数据
- 常见content_type:
- ‘text/html’: 默认的,HTML文件
- ‘text/plain’: 纯文本
- ‘text/css’: css文件
- ‘text/javascript’: js文件
- ‘multipart/form-data’: 文件提交
- ‘application/json’: json传输
- ‘application/xml’: xml文件
- 常见content_type:
- HttpResponse子类
类型 作用 状态码 HttpResponseRedirect 重定向 302 HttpResponseNotModified 未修改 304 HttpResponseBadRequest 错误请求 400 HttpResponseNotFound 没有对应的资源 404 HttpResponseForbidden 请求被禁止 403 HttpResponseServerError 服务器错误 500
2.2 GET请求和POST请求
- 定义:
- 无论是GET还是POST,统一都由视图函数接收,通过判断request.method区分具体的请求动作
- 样例
if request.method == 'GET': 处理get请求时的业务逻辑 elif request.method == 'POST': 处理POST请求时的业务逻辑 else: 处理其他请求业务的逻辑
- GET处理
- GET请求动作一般用于向服务器获取数据
- 能够产生GET请求的场景
- 浏览器地址栏输入URL回车后
<a href = "地址?参数=值&参数=值">
- form表单中的method为get
- GET请求中,如果有数据需要传递给服务器,通常会用查询字符串(Query String)传递,注意不要传递敏感数据
- URL格式:XXX?参数名1=值&参数名2=值(如:http://127.0.0.1:8000?a=100&b=200)
- 服务器端接收参数:获取客户端请求GET提交的数据方法示例
request.GET['参数名'] #得到该参数名的值 request.GET.get('参数名',’默认值‘) #得到该参数名的值,如果该参数名不存在则返回默认值 request.GET.getlist(’参数名‘) #如果该参数名存在多个返回值,则用getlist来接收```
- POST 处理
- POST请求动作一般用于向服务器提交大量/隐私数据
- 客户端通过表单等POST请求将数据传递给服务器端;如:
<form method='post' action="/login"> #action指明post请求发给哪个路由 姓名:<input type="text" name="username"> <input type='submit' value='登陆'> </form>
- 服务器端接收参数:通过request.method来判断是否为post请求
- 使用post方式接收客户端数据
request.POST['参数名'] #得到该参数名的值 request.POST.get('参数名',’默认值‘) #得到该参数名的值,如果该参数名不存在则返回默认值 request.POST.getlist(’参数名‘) #如果该参数名存在多个返回值,则用getlist来接收
- 注意:发送POST请求时,django需要取消csrf验证,否则django会拒绝客户端发来的POST请求,报403响应
- 取消csrf验证:注释掉settings.py文件中的MIDDLEWARE中的csrfviewsmiddleware的中间件
2.3 Django的设计模式(MTV)
- 设计模式:MVC和MTV
- MVC(model-view-controller)模型-视图-控制器模式
- M 模型层,主要用于对数据库层的封装
- V 视图层,用于向用户展示结果
- C 控制层,用于处理请求、获取数据、返回结果
- 优点:降低模块间的耦合度
- MTV (model-template-view) 模型-模版-视图模式
- M 模型层,负责与数据库交互
- T 模板层,负责呈现内容到浏览器(html)
- V 视图层,负责接收请求、获取数据、返回结果
- 优点:降低模块间的耦合度
- MVC(model-view-controller)模型-视图-控制器模式
2.4 模板层
-
模板定义:
- 模板是可以根据字典数据动态变化的HTML网页
- 模板可以根据视图中传递的字典数据动态生成相应的HTML网页
-
模板配置
- 创建模板文件夹<项目名>/templates
- 在settings.py中TEMPLATES配置项
- BACKEND:指定模板的引擎
- DIRS:模板的搜索目录,可以是一个或多个
- APP_DIRS:是否要在子应用中的templates文件夹中搜索模板文件
- OPTIONS:有关模板的选项
- 配置中需修改的部分
- 设置DIRS - ‘DIRS’:[os.path.join(BASE_DIR,‘templates’)],
-
模板的加载方式
- 方案一:通过loader获取模板,通过HttpResponse进行响应,在视图函数中进行如下配置
from django.template import loader t = loader.get_template("模板文件名") #通过loader加载模板,得到一个loader对象 html = t.render(字典数据) #将t(loader对象)转换成HTML字符串 return HttpResponse(html) #用响应对象的方式将转换的字符串内容返回给浏览器
- 方案2:使用render()直接加载并响应模板,在函数视图中进行如下配置
from django.shortcuts import render return render(request,'模板文件名',字典数据)
- 方案一:通过loader获取模板,通过HttpResponse进行响应,在视图函数中进行如下配置
-
视图层与模板层之间的交互
- 视图函数中可以将python变量封装到字典中传递到模板;样例:
def xxx_view(request): dic = { "变量1":"值1", "变量2":"值2", } return render(request,'xxx.html',dic)
- 在模板中,我们可以使用 { {变量名}} 的语法调用视图传进来的变量
- 视图函数中可以将python变量封装到字典中传递到模板;样例:
-
模板层-变量
- 模板层可接收的数据类型
类型名 注释 str 字符串 int 整型 list 列表 tuple 元组 dict 字典 func 方法 obj 类实例化对象 - 在模板中使用变量语法
- { { 变量名 }}
- { { 变量名.index }} #传入的变量为列表、元组等,可用.index方法取出其中的元素
- { { 变量名.key }} #传入的变量为字典,可用.key方法获取key所对应的值
- { { 对象.方法 }} #调用对象的方法
- { { 函数名 }} #调用函数
- 模板标签
-
作用:将一些服务器端的功能嵌入到模板中,例如流程控制等
-
语法:
{ % 标签 %} ………… { % 结束标签 %} #django中大部分标签都需要使用结束标签封口
-
IF标签
- 语法
{ % if 条件表达式1 %} …… { % elif 条件表达式2 %} …… { % else %} …… { % endif %} #必须使用endif标签进行结束
- 注意:
- if条件表达式例可以用的运算符==,!=,<,>,<=,>=,in.not in,is,is not,not,and,or;
- 在if标记中使用实际括号是无效的语法,如果需要他们指示优先级,则应使用嵌套的if标记
- if语句中,运算符两侧不能紧挨变量或常量,必须用空格隔开
- 关于if标签的语法参考官方文档
- 样例
<form action='/text' method="post"> <input type="text" name="x" value='{ { x }}'> <select name="op"> <option value="add" { %if op == 'add' %}selected{ %endif%}> +加</option> <option value="sub" { %if op == 'sub' %}selected{ %endif%}> -减</option> <option value="mul" { %if op == 'mul' %}selected{ %endif%}> *乘</option> <option value="div" { %if op == 'div' %}selected{ %endif%}> /除</option> </select> <input type="text" name="y" value='{ { y }}'> = <span>{ { result }}</span> <div><input type="submit" value="开始计算"> </div> </form>
- 语法
-
for 标签
- 语法:
{ % for 变量 in 可迭代对象 %} …… 循环语句 { % empty %} …… 可迭代对象为空时显示的语句 { % endfor %}
- 可迭代对象的传递,从视图函数以字典形式传递给模板文件,需要保证模板文件中的可迭代对象名与视图函数中定义的键名相同
<h3>{% for i in x %}{ { forloop.counter }}this is in for { {i}} {%endfor%}</h3> # x由视图函数传入
- 关于for标签的语法参考官方文档
- 语法:
-
内置变量 - forloop
变量 描述 forloop.counter 返回当前循环的索引(从1开始索引) forloop.counter0 返回当前循环的索引(从0开始索引) forloop.revcounter 返回当前循环的索引(从1开始索引counter值的倒序) forloop.revcounter0 返回当前循环的索引(从0开始索引counter值的倒序) forloop.first 如果当前循环是第一次循环,则返回True forloop.last 如果当前循环是最后一次循环,则返回True forloop.parentloop 如果为嵌套循环,parentloop则表示外层循环
-
- 模板过滤器
-
定义:在变量输出时,对变量的值进行处理
-
作用:可以通过使用过滤器来改变变量的输出显示
-
语法:{ {变量|过滤器1:‘参数值1’ | 过滤器2:‘参数值2’}}
-
关于过滤器的语法参考官方文档
-
常用过滤器:
过滤器 说明 lower 将字符串转换为全部小写 upper 将字符串转换为全部大写 safe 禁用转义,告诉模板这个变量是安全的,可以解释执行 add:“n” 将value的值增加n default:“默认值” 变量不存在时,返回默认值 truncatechars:‘n’ 如果字符串的字符多余指定的字符数量,那么会被截断,截断的字符串将以可翻译的省略号序列("…")结尾
-
- 模板的继承
- 定义:模板的继承可以使父模板的内容重用,子模板直接继承父模板的全部内容并可以覆盖父模板中相应的块
- 语法 - 父模板中:
- 定义父模板中的块block标签
- 标识出哪些在子模块中是允许被修改的(block标记的继承时都是可以进行修改的)
- block标签:在父模板中定义,可以在子模板中覆盖
- 语法 - 子模板中:
- 继承模板extends标签(写在模板文件的第一行)
- 例如
{% extends 'base.html '%}
#继承父模板base.html
- 例如
- 子模板重写父模板中的内容块
{ % block block_name %} 子模板块用来覆盖父模板中 block_name 块的内容 { % endblock block_name %} #block_name可省略
- 继承模板extends标签(写在模板文件的第一行)
- 重写的覆盖规则:
- 不重写,将按照父模板的效果显示
- 重写,则按照重写效果显示
- 注意:模板继承时,服务器端的动态内容无法继承,例如:视图给父模板传递的变量,在子模板中无法拿到
- 例:父模板中
子模板中{ % block block_name %} <h4>this is in parent</h4> { % endblock %}
{ % extends 'test_html.html' %} { % block block_name %} <h3> this is in base.