一个动态网站需要实现的如下几个基本功能,而框架本质就是对下面的功能进行封装和扩展
- html模板
- url (路由)
- socket (request请求和响应功能)
MTV设计模式
Django借鉴了MVC模式,将交互过程也分为三个层次
- Model:数据存储层,处理所有数据相关的业务,和数据库进行交互,并提供数据的增删改查;
- Template:模板层(也叫表现层)具体来处理页面的显示;
- View:业务逻辑层,处理具体的业务逻辑,它的作用是连通Model 层和 Template 。
同样我们也对 MTV 设计模式的请求与响应过程进行描述:
-
用户通过浏览器对服务器发起 request 请求,服务器接收请求后,通过 View 的业务逻辑层进行分析,同时向 Model 层和 Template 层发送指令;
-
Mole 层与数据库进行交互,将数据返回给 View 层;
-
Template 层接收到指令后,调用相应的模板,并返回给 View 层;
-
View 层接收到模板与数据后,首先对模板进行渲染(即将相应的数据赋值给模板),然后组织成响应格式返回给浏览器,浏览器进行解析后并最终呈现给用户。
安装框架
如果不指定安装版本就默认安装最新的版本,由于国内下载较慢需要换源
pip install django -i https://pypi.douban.com/simple
# pip install django==1.11 -i https://pypi.douban.com/simple #指定安装版本
注意:Django3.0版本的和Python3.7.0版本一起运行有bug,会发现Django的admin页面不能访问,升级到Python3.7.1版本或以上就可解决
初始化目录
使用该命令,会在该目录下生成一个文件和文件夹,用于实现一个项目最基本的功能
pycharm中可以不使用命令创建
# django-admin startproject 项目名称
D:\Python代码\django\>django-admin startproject taojin
- manage.py(配置管理器,使用命令行的方式管理整个网站)
- db.sqlite3(初始化时没有,运行起来后才有)
- taojin
-
- __init__.py(Python包管理机制必须有的文件)
- sagi.py
- settings.py(配置文件,例如连接数据库的配置信息)
- urls.py(url路由功能,项目中所有的地址页面都需要在这里配置url)
- wsgi.py(socket请求响应功能,后期可以是用nginx替换它)
启动项目
使用manage.py的命令行启动,先进入项目的目录,然后启动监听8080端口
127.0.0.1只是在本地测试时使用,这样不能被局域网的其它主机访问,可使用 0.0.0.0
D:\Python代码\django\>cd taojin
D:\Python代码\django\taojin\>python manage.py runserver 127.0.0.1:8080
每次都要到cmd中敲命令麻烦,可以随便创建一个py文件写入如下内容,以后只运行该文件就行了:
import os
os.system('python D:/Python代码/django/taojin/manage.py runserver 127.0.0.1:8080')
视图函数
视图是MTV模式中的V层,实现业务逻辑的关键层。视图函数是Django中函数或者类,视图函数首先通过接收来自浏览器的请求,并最终返回响应。
# taojin/taojin/urls.py
from django.contrib import admin
from django.urls import path
from django.http import HttpResponse # 要导入该类
def My_love(request): # 视图函数
return HttpResponse('<h1>I Love You<h1>')
urlpatterns = [
path('admin/', admin.site.urls),
path('love/', My_love), # 自己写的path
]
-
HttpResponse是视图的响应类型,必须要导入,并在返回结果时使用该类,将转化字符串等转为响应类型
-
视图函数至少有一个参数,并且第一个参数必须为request。request指向的是HttpRequest请求类型的对象,他携带了浏览器的请求信息
-
视图函数要返回响应内容,可以返回文件、HTML标签、303重定向等等,这里的响应内容是自己写的HTML标签,它作为HttpResponse的对象返回给浏览器
-
urlpatterns变量保存 请求的url 和 视图函数 的映射
Django 收到请求以后,首先创建一个带有请求信息的 HttpRequset 对象,将 HttpRequest 的对象 request 作为第一个参数传递给视图函数,视图接收参数后继续向下执行,然后选择加载对应的视图,最后返回 HttpResponse 对象给浏览器。
模板系统
我们希望将html模板代码放在某个目录下统一管理,以实现视图层和模板层的解耦。我们在项目的根目录下创建一个templates的目录,下面放置html文件。
首先修改配置文件,taojin/taojin/settings.py文件中的TEMPLATES属性的 ‘DIRS’ 键要设置值为html模板的目录,这样视图层才能在对应的路径下找到html文件
'DIRS': [os.path.join(BASE_DIR, 'templates')], # os.path.join(BASE_DIR)代表项目的路径,templates代表html文件所在的目录
这样就可以在taojin/taojin/urls.py文件中写业务逻辑
from django.shortcuts import render
def My_cat(request):
return render(request, 'mycat.html', {"name": "tomcat"})
urlpatterns = [
path('buycat/', My_cat),
]
# taojin/templates/mycat.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MyCat</title>
</head>
<body>
<h1>我的名字:</h1> {{name}}
</body>
</html>
render类内部封装的还是HttpResponse类,但附加的功能可以实现传递文件名,而不需要打开读取文件操作
Django中间件
中间件可以理解为是一个可插拔插件(添加中间件类和注释中间件类),本质是一个Python写的一个类,可以在接收HttpRequest后对数据处理,然后执行视图函数返回HttpResponse,然后再次执行中间件处理HttpResponse数据后返回。在 taojin/taojin/settings.py 文件的 MIDDLEWARE 属性中使用,它们从上往下依次执行中间件类,但返回视图后,再次调用是从后往上依次返回。
额外配置:注释一个中间件类,该中间件主要防止CSRF跨域请求攻击,但如果使用了templates的html模板,就不能使用该功能,因而要注释掉。
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',
]
静态文件
静态资源:css、html、js、图片、视频等
如果在html文件中还使用到css样式文件,或者其它文件,但css样式文件和html类似在项目下建文件夹stat,然后在stat文件夹里面写css文件,这样的话Django就找不到css文件。就要修改settings.py文件,在里面的最后添加以下内容
# STATIC_URL = '/static/' # 文件自带
STATICFILES_DIRS = ( # 代表寻找静态资源时到该目录寻找
os.path.join(BASE_DIR, 'stat'),
)
STATIC_URL代表访问静态资源的前缀,那么最后调用时为 /static/stat/cat.css ,这样还要加前缀,不方便,所以最好建立静态资源目录时,文件夹的名字为static,而不使用stat或其它
# STATIC_URL = '/static/' # 文件自带
STATICFILES_DIRS = ( # 代表寻找静态资源时到该目录寻找
os.path.join(BASE_DIR, 'static'),
)
css文件和html文件写法
// cat.css
h1{
color: red;
}
<--!mycat.html-->
<link rel="stylesheet" href="/static/cat.css">
定制返回结果
请求方法常用的有GET和POST,可根据不同的请求响应不同的内容。GET请求一般通过链接请求,可返回对应的页面就行;POST通常用于提交数据,在后台获取后进行处理
request.method保存的是请求的方法,POST提交的数据以字典的方式保存于request.POST中,对应的request.GET是GET请求的数据
使用<form method=“POST” action="/login?id=2">时,request的GET和POST中都有值
from django.shortcuts import render, redirect
def Login(request):
if request.method == 'GET':
return render(request, 'login.html')
else:
# us = request.POST['user'] # 不推荐使用该方法,如果找不到就报错
us = request.POST.get('user') # 如果找不到就设为None
pa = request.POST.get('pwd')
if us == 'root' and pa == 'admin':
print('登陆成功,跳转到百度')
return redirect('https://www.baidu.com')
else:
print('登陆失败,重新登陆')
return render(request, 'login.html', {"mes": "用户名或密码错误"})
urlpatterns = [
path('login/', Login),
]
<--!login.html-->
<form method="POST" action="/login">
<input type="text" name="user" /><br/>
<input type="password" name="pwd" /><br/>
<input type="submit" value="登陆" />
</form>
{{mes}}
模板语言特殊标记
HTML可以嵌入后台语言(Python),模板渲染语法:{%命令%}、{{变量名}}
{{变量名}}:在html中使用,视图函数返回传参时,使用字典的方式传递
# mycat.html
<h1>
{{name}}<br>
{{users.0}}<br> # 与python不同的索引的方式取值
{{users.1}}<br>
{{vip.num1}}<br>
{{vip.num2}}<br>
使用for循环:
<ul>
{% for i in users %}
<li>{{ i }}</li>
{% endfor %}
{% if 1==2 %}
twono
{% elif 1=3 %}
threeno
{% else %}
yes
{% endif %}
</ul>
</h1>
# urls.py
def My_cat(request):
return render(request, 'mycat.html', {
"name": "tomcat",
"users": ['哈士奇', '阿黄'],
"vip": {
"num1": "VIP5",
"num2": "VIP6"
}
}
)
创建应用
前面启动的项目是Django自带的模板,我们以后可能不会使用到,所以要自己建立网站,就必须懂得使用manage.py创建一个app。并且使用前面的写法写的话,urls.py文件的内容就太多了,所以要将urlpatterns和视图函数分开实现解耦,urlpatterns还是原来的位置,但视图函数放入应用的views.py中
# Django支持在一个项目下创建多个app,并且我们自己搭的app也要使用该命令
D:\Python代码\django\taojin>python manage.py startapp oneapp # 网站的名称为oneapp
使用命令后就在项目的目录下生成了一堆文件:
- admin.py 用于将 Model 定义的数据表注册到管理后台,是 Django Admin 应用的配置文件;
- apps.py 用于应用程序本身的属性配置文件;
- models.py 用于定义应用中所需要的数据表;
- tests.py 文件用于编写当前应用程序的单元测试;
- views.py 用来定义视图处理函数的文件;
- 一级目录下的 init.py 文件标识 index 应用是一个 Python 包;
- migrations 目录用于存储数据库迁移时生成的文件,该目录下的 __init__.py 文件标识 migrations 是一个 Python 包。
然后在项目的settings.py文件中修改添加内容
INSTALLED_APPS = [
'oneapp',
]
特么的,如果使用Pycharm创建的Django就不会有问题,但是我是用命令创建的Django和应用,导入应用时Pycharm在导入语句处有红色线,我还以为不行害得我烦死了,原来是可以的。
此时就可以实战了
# taojin/oneapp/views.py
from django.http import HttpResponse
def My_love(request):
return HttpResponse('<h1>I Love You<h1>')
# taojin/taojin/urls.py
from django.contrib import admin
from django.urls import path
from oneapp import views
urlpatterns = [
path('love/', views.My_love),
]