# 4.Django
#### 1.web工作流程
![1557817374112](assets/1557817374112.png)
2.mvt和mvc的区别
![1557818914560](assets/1557818914560.png)
- M全拼为Model,主要封装对数据库层的访问,对数据库中的数据进行增、删、改、查操作。
- V全拼为View,用于封装结果,生成页面展示的html内容。
- C全拼为Controller,用于接收请求,处理业务逻辑,与Model和View交互,返回结果。
- ![1557819145918](assets/1557819145918.png)
![1557819163646](assets/1557819163646.png)
![1557819188682](assets/1557819188682.png)
#### 2.环境安装
##### 1.创建虚拟环境
虚拟环境的作用:
作用 : 虚拟环境可以搭建独立的python运行环境, 使得单个项目的运行环境与其它项目互不影响.
所有的虚拟环境都位于/home/下的隐藏目录.virtualenvs下
1. 创建虚拟环境
创建虚拟环境之前先看一下现有的虚拟环境 workon
```shell
mkvirtualenv django_py3_1.11 -p python3
```
注意需要联网
2. 安装Django
使用django 1.11.11版本,注意需要联网
```shell
pip install django==1.11.11
```
需要在虚拟环境下进行安装 否则会查找不到
3. 复习虚拟环境和pip的命令
```shell
# 虚拟环境
mkvirtualenv # 创建虚拟环境
rmvirtualenv # 删除虚拟环境
workon # 进入虚拟环境、查看所有虚拟环境
deactivate # 退出虚拟环境
# pip
pip install # 安装依赖包
pip uninstall # 卸载依赖包
pip list # 查看已安装的依赖库
一般使用pip3
```
##### 2.创建工程
1.创建工程文件夹
```shell
django-admin startproject 工程名称
```
执行后,会多出一个新目录名为demo,此即为新创建的工程目录。
![1557821571326](assets/1557821571326.png)
- 与项目同名的目录,此处为demo。
- **settings.py** 是项目的整体配置文件。
- **urls.py** 是项目的URL配置文件。 配置路由
- **wsgi.py** 是项目与WSGI兼容的Web服务器入口。
- **manage.py** 是项目管理文件,通过它管理项目。
##### 3.测试运行
显示端口被占用:sudo fuser -k 8000/tcp 杀掉端口为8000的服务
运行服务器命令如下:
```shell
python manage.py runserver ip:端口
或:
python manage.py runserver
```
- 默认地址为 http://127.0.0.1:8000/
- django默认工作在调式Debug模式下,如果增加、修改、删除文件,服务器会自动重启。
- 按ctrl+c停止服务器
##### 4.创建子程序
在Web应用中,通常有一些业务功能模块是在不同的项目中都可以复用的,故在开发中通常将工程项目拆分为不同的子功能模块,各功能模块间可以保持相对的独立,在其他工程项目中需要用到某个特定功能模块时,可以将该模块代码整体复制过去,达到复用。
###### 1.创建
创建子应用依然可以通过命令行执行,需要执行manage.py文件进行修改,**manage.py** 为上述创建工程时自动生成的管理文件。
```
python manage.py startapp 子应用名称
```
注意所有的应用都必须在虚拟环境中运行
生成结果:![1557822779188](assets/1557822779188.png)
- **admin.py** 文件跟网站的后台管理站点配置相关。
- **apps.py** 文件用于配置当前子应用的相关信息。应用配置文件 主文件中setting是配置文件
- **migrations** 目录用于存放数据库迁移历史文件。
- **models.py** 文件用户保存数据库模型类。
- **tests.py** 文件用于开发测试用例,编写单元测试。
- **views.py** 文件用于编写Web应用视图。
###### 2.注册和安装子程序
创建出来的子应用目录文件虽然被放到了工程项目目录中,但是django工程并不能立即直接使用该子应用,需要注册安装后才能使用。
在工程配置文件settings.py中,**INSTALLED_APPS**项保存了工程中已经注册安装的子应用,初始工程中的INSTALLED_APPS如下:
1.0版本之前需要在前面加根目录名 此处为demo
![1557823196294](assets/1557823196294.png)
注册安装一个子应用的方法,即是将子应用的配置信息文件apps.py中的Config类添加到INSTALLED_APPS列表中。
##### 5.创建视图
视图即可以通过url访问
Django的视图是定义在子应用的views.py中的。
此处应用到了views的业务逻辑方面用法
1.在views中编写视图代码
views:
```python
from django.shortcuts import render
# 创建视图1. 导入响应报文函数
from django.http.response import HttpResponse
# 用于反推路径
from django.urls import reverse
# Create your views here.
# 创建视图函数在这里
# 这里是访问窗口后执行的函数 所以需要返回一个相应头
# 需要接收请求报文 必须接收 因为返回值的方法需要接收一个参数
def index(request):
#作用1.接收请求报文
#2.解析请求对象
#3.model template的中间站
#4.发送响应报文
print(reverse('user:index'))
#只能以此方式发送响应报文
return HttpResponse('这里是来自李叔叔的1号响应报文')
```
2.urls配置路由
urls:
```python
from django.conf.urls import url
#此处为自定义模块 用于导入路由
from . import views
#创建视图2 设置路由 url路径可以使用正则表达式
urlpatterns = [
url(r'^index/$', views.index, name='index'),
url(r'^indextwo/$', views.indextwo, name='index')
]
```
1. 每个函数需要建立一个路由,路由需要和函数进行匹配
2. 导入函数地址时需要导入函数之前需要先导入views文件
3.总路由中添加子程序的路由
主应用urls:
```python
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 对于配置子应用的路由,需要使用include方法 (子路由路径)
url(r'^user/',include('user.urls',namespace='user')),
#todo 不能全匹配 因为这里只是有一部分信息 末尾不能加$
url(r'^demorequest/',include('demorequest.urls',namespace="demorequest"))
# 路由设置 第二种路由的写法 直接导入模块包
# url(r'^user/',user.views.index)
]
```
- Include的两种导入方式
- - 1. 字符串方式:include(‘urls的路径’)’
- - 2. 导入包的形式:include(路径)
From . import 路径名称 相对路径写法
##### 6 pycharm中环境的切换
![1558000519837](../../%E7%AC%94%E8%AE%B0/%E5%8D%95%E6%97%A5%E7%AC%94%E8%AE%B0django/assets/1558000519837.png)
- 设置该虚拟环境
- 路径为:/home/python/.virtualenvs/my_django_py3_1.11/bin/python3
- /home/python/.virtualenvs 这个是虚拟环境的路径
- ![1558000613258](../../%E7%AC%94%E8%AE%B0/%E5%8D%95%E6%97%A5%E7%AC%94%E8%AE%B0django/assets/1558000613258.png)
##### 7.pycharm中直接运行manger.py
由于本程序运行时需要使用命令行`python3 manger.py runstart`,所以在pycharm中无法直接运行 ,进而使用修改启动方法,让程序可以直接在pycharm中运行
![1558001197253](assets/1558001197253.png)
##### 8.git的使用
1. 进入文件根目录 使用口令 git init
2. pycharm需要重新启动一下
3. 快捷键ctrl+k 可以commit
#### 3.配置、静态文件与路由
##### 1.路由说明
###### 1.路由的定义方式
1.每个子应用为了保持相对独立,可以在各个子应用中定义属于自己的urls.py来保存该应用的路由。然后用主路由文件包含各应用的子路由数据。
子路由中urls代码
```python
from django.conf.urls import url
#此处为自定义模块 用于导入路由
from . import views
#创建视图2 设置路由 url路径可以使用正则表达式
urlpatterns = [
url(r'^index/', views.index)
]
```
主路由中url代码
```python
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^user/',include('user.urls')),
]
```
2.将工程的全部路由信息都定义在主路由文件中,子应用不再设置urls.py。如:
```python
from django.conf.urls import url,include
from django.contrib import admin
import user.views
urlpatterns = [
url(r'^admin/', admin.site.urls)
# 路由设置 第二种路由的写法 直接导入模块包,根据相对路径书写
url(r'^user/',user.views.index)
]
```
###### 2.路由解析的顺序
路由解析顺序是由上至下,有可能会使上面的路由屏蔽掉下面的路由,带来非预期结果。
案例:
同时设置2个响应函数 ,第一个函数名为index,第二个函数名为index2
url匹配时没有加后面的/%后缀,
匹配结果:会优先匹配前面的一个函数
###### 3.路由命名与reverse反解析(逆向)
1.路由的命名:
在(urls 主程序路由配置)使用include函数(即主页中)定义路由时,可以使用namespace参数定义路由的命名空间,
且在子程序的urls的路由配置中,可以使用name参数给路由命名
命名空间表示,凡是user.urls中定义的路由,均属于namespace指明的user名下。
**命名空间的作用:避免不同应用中的路由使用了相同的名字发生冲突,使用命名空间区别开。**
2.reverse反解析
使用reverse函数,可以根据路由名称,返回具体的路径
- 对于未指明namespace的,reverse(路由name)
- def index(request):
```
print(reverse('user:index'))
#只能以此方式发送响应报文
return HttpResponse('这里是来自李叔叔的1号响应报文')
```
- 对于指明namespace的,reverse(命名空间namespace:路由name)
```
def index(request):
print(reverse('index'))
#只能以此方式发送响应报文
return HttpResponse('这里是来自李叔叔的1号响应报文')
```
指定了spacename必须使用前面一种
反解析的应用:
- 对于类似注册 提交订单之后会返回网站的主页面,就可以通过反解析 根据spacename和name来动态关联主页,以后主页名称修改了也不会造成影响.
##### 2.配置文件
1.base_dir
当前工程的根目录,Django会依此来定位工程内的相关文件,我们也可以使用该参数来构造文件路径。
进行3次去掉文件名 返回目录的操作 即可获得最外层文件的绝对路径
![1557925690741](assets/1557925690741.png)
2.debug
```python
#设置是否调试模式 ,即生产模式需要把debug修改为False 注意大小写 这里是为了应对404页面
#SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
#You must set settings.ALLOWED_HOSTS if DEBUG is False. 设置了非调试模式必须设置允许的域名 一般设置为空 表示全部允许 即ALLOWED_HOSTS = [' ']
ALLOWED_HOSTS = []
```
3.Application definition 注册子应用
```python
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#注册子应用 子应用中路径.apps.userConfig
'user.apps.UserConfig',
]
```
ps:子应用的注册:命令行中输入:python manage.py startapp 子应用名称
4.本地化语言时区:
初始化的工程默认语言和时区为英语和UTC标准时区
```python
LANGUAGE_CODE = 'en-us' # 语言
TIME_ZONE = 'UTC' # 时区
```
将语言和时区修改为中国大陆信息
```python
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
```
调试模式的404页面
![1557924451841](assets/1557924451841.png)
非调试模式的404页面:
![1557925888630](assets/1557925888630.png)
##### 3.静态文件配置
项目中的CSS、图片、js都是静态文件。一般会将静态文件放到一个单独的目录中,以方便管理。在html页面中调用时,也需要指定静态文件的路径,Django中提供了一种解析的方式配置静态文件路径。静态文件可以放在项目根目录下,也可以放在应用的目录下,由于有些静态文件在项目中是通用的,所以推荐放在项目的根目录下,方便管理。
同样是在setting.py中配置的
```
# 静态文件CSS, JavaScript, Images
# STATIC_URL访问静态文件的URL前缀
STATIC_URL = '/static/'
#STATICFILES_DIRS=[] 存放查找静态文件的目录 接收的是list
#STATICFILES_DIRS=['static_files']
STATICFILES_DIRS=[os.path.join(BASE_DIR,'static_files')]
```
- STATICFILES_DIRS的值为['/home/python/Desktop/demo/static_files'] 绝对路径
- BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(`__file__`))),意思是 主文件的绝对路径
- os.path.join()函数用于路径拼接文件路径。
- - 会从第一个以”/”开头的参数开始拼接,之前的参数全部丢弃。
- 以上一种情况为先。在上一种情况确保情况下,若出现”./”开头的参数,会从”./”开头的参数的上一个参数开始拼接。
静态文件夹可以有多个 如果多个文件夹中有同名的文件,按照STATICFILES_DIRS列表中的文件导入顺序寻找动态文件夹
以当前的设置访问静态文件的话 url为:172.0.0.1:8000/static/动态文件名
![1557926900821](assets/1557926900821.png)
#### 4.请求与响应
##### 1.请求对象传参 4种
###### 1.url请求路径传参
**方法1:**
提取URL的特定部分,如资源路径为:/beijing/2018,可以在服务器端的路由中用正则表达式截取;
1. 在路由中设置匹配的正则表达式 此处以资源路径为/beijing/2018为例:
2. ```python
urlpatterns = [
#url路径中的/为路径自带的/
# \d:匹配一个数字0-9 +:匹配前面的子表达式一次或多次。
#[a-z]+ 匹配a-z 至少出现一次
url(r'^index/(\d+)/([a-z]+)/', views.index,name='demorequest_index'),
]
```
3. 获取到该函数后,在视图函数中对其路径进行解析
4. 视图函数有默认的位置参数,第一个为request 格式为:
- <WSGIRequest: GET '/demorequest/index/2008/beijing/'>
5. 资源中的第一部分 此题中为beijing
6. 以此类推 第二个为第二个/后的部分 为2018
7. 传递了几个参数就只能接收几个参数,多出了话会报错
**string{}.format(str):使用str代替{} 相当于一个占位符 %**
**方法2**
此方法从仅为正则表达式的不同,对正则表达式的的组进行命名, 命名和视图函数中的参数名一致,如果这样的话可以不用按照顺序传递参数
- **正则表达式给一个组中的数据取名:(?P<要取的名字>正则表达式)**
###### 2.查询字符串
形如key1=value1&key2=value2;
**查询参数的获取**:
1. request.GET(获取查询参数) 和请求方式无关 只是获取查询字符串的
```
返回值为:<QueryDict: {'a': ['10','20'], 'b': ['2']}>
```
- 返回值是一个QueryDict对象
- ```
关于QueryDict对象:
定义在django.http.QueryDict
HttpRequest对象的属性GET、POST都是QueryDict类型的对象
与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值的情况
```
- 对于同一个key 可以赋予多个值,放在一个列表中
2. 对于单个查询参数的获取:
- QueryDict对象.get(键) 可以获得键的值 如果值有多个,只返回最后一个
- QueryDict对象.getlist(键) 可以获得键的值组成的列表 可以遍历出结果
- ```python
def findstring(request):
result = request.GET
print(result)
key_a=result.getlist('a')
print(key_a)
return HttpResponse('这里是查询字符串函数返回的返回值')
<<<['10']
```
解决postman问题
![1557935363212](assets/1557935363212.png)
###### 3.请求体传参
1.from-data(表单)数据类型
前端发送的表单类型的请求体数据,可以通过request.POST属性获取,返回QueryDict对象。
**重要:request.POST只能用来获取POST方式的请求体表单数据。**
```python
#请求头fromdata传参
def fromdata(request):
#request.POST只能用来获取POST方式的请求体表单数据。
result = request.POST
print(result)
value_b = result.get('b')
print(value_b)
value_a = result.getlist('a')
print(value_a)
return HttpResponse('fromdata传参')
```
使用post请求方式,同样返回的是一个QueryDict对象 但是需要使用.post来获取
获取表单中值的方法和之前的一个 get和getlist
###### postman的使用
![1557940671877](assets/1557940671877.png)
###### 4.非表单类型
Non-Form Data
此处以json字符串为例:
![1557940751119](assets/1557940751119.png)
首先要进行如此选择,才可以发送json数据
![1557941666835](assets/1557941666835.png) |
|