Django是使用Python编写的一个WEB服务器应用框架,使用MTV模型。
Django实现的流程:
1、安装Django:pip install django
安装完毕后,在python目录下的scripts子目录下有
2、创建 项目project
在D盘根目录下运行:django-admin startproject 项目名称,如果找不到命令,需要在环境变量中增加上面的scripts路径。例如
django-admin startproject mypyweb
会在D盘根目录下创建mypyweb目录:
其中,manage.py是启动文件,提供对项目进行管理的各种命令工具,通过它可以调用django shell和数据库等,子目录mypyweb中包含settings.py是对项目的配置文件,包括数据库信息,调试标志以及其他一些工作的变量,urls.py就是前面说过的urls.py,资源路径分配文件,负责把URL模式映射到应用程序。
3、创建APP,一个项目(也就是一个站点)可能包含一个或多个应用。
在项目目录下,运行:Python manage.py startapp 应用名,如:
python manage.py startapp blog
会在项目目录下创建blog子目录,其下最主要的是models.py和views.py,分别是与数据库交互的模块和View层的功能函数模块,migrations子目录是与数据库操作有关的目录。
4、此时一个项目和应用的框架就创建好了,可以启动项目了
启动项目的命令:python manage.py runserver 8008
在pycharm中可以使用图形界面完成上述过程:
设置好后,点击Create按钮创建项目和应用。
我在测试解释器使用虚拟环境时,一直出错误,直接用的已存在的解释器。
创建完成后显示:
这里直接打开了urls.py,可以看到资源路径分配,一开始都是:
urlpatterns = [
path('admin/',admin.site.urls),
]
对于这个列表,是Django高版本的写法,低版本使用的是url:
urlpatterns = [
url(r'^admin/',admin.site.urls),
]
url是Django 1.x中的写法,从Django2.1开始中,开始舍弃Django1.x中的url写法。在Django2.x中,描写url配置的有两个函数path和re_path,re_path()函数可以看做是django 1.x中得url函数,即可以在路径中使用正则。path与url是两个不同的模块,效果都是响应返回页面, path调用的是python第三方模块或框架,而url则是自定义的模块,如Views下的def函数对应你url中的参数值.
简单写一个网页测试一下:
实现前面的显示时间的网页例子:
首先修改urls.py,增加一个转换器项:
第二步,在app01应用中的views.py中增加cur_time函数:
第三步:启动Django项目:
在终端窗口使用:python manage.py runserver ip:port启动,如果
python manage.py runserver 127.0.0.1:8008,如果不加IP地址,直接接端口号,默认在127.0.0.1地址上启动。
也可以在pycharm上以图形界面配置启动:
什么也不配置,默认就是在127.0.0.1:8000端口启动,按绿色三角按钮就可以启动
访问这个路径:
因为我们的urls中没有/根目录,所以出错。 加上正确的访问地址:
修改views.py中cur_time函数,使用模板文件cur_time.html,在templates目录下建立这个文件
注意这里的{{ abc }},是要被替换的内容。
修改views.py中的cur_time函数:
import datetime
# Create your views here.
def cur_time(request):
base_p = Path(__file__).resolve().parent.parent
templates = os.path.join(base_p, 'templates')
print(templates)
times = datetime.datetime.now()
return render(request,"cur_time.html",{"abc":times})
# 这里使用render来返回一个经过渲染的模板文件,这里就是cur_time.html
# 这里cur_time.html是保存在templates目录中,可以直接写文件名
# Django能够直接找到这个文件,是因为在settings.py配置文件中已经对相关目录进行了配置
# 注意settings.py中TEMPLATES的设置,函数中的base_p和templates就是settings.py中的BASE_DIR和TEMPLATES
这里一是要注意render这个函数,是用来渲染模板并返回的,二要注意保存在templates目录中的模板在这里可以直接写文件名,三是第三个参数,是一个字典,字典的key就是模板中{{abc}}的名字,这样在模板中碰到{{abc}},就会被times变量值替换。打印出的路径是:D:\MyPySite\templates,所以Django能够直接找到模板文件。
settings中的配置:
访问的结果:
最后反馈给客户端的都是HttpResponse的实例,render则是要先渲染,然后将渲染的结果使用HttpResponse返回给客户端。
前后端交互(非常重要,前端数据如何发送到后台):
B/S架构的系统,最重要的就是将前端的数据发给后台服务器,服务器接收后经过处理反馈结果给前端。
前端发送数据给后端服务器的一种方法是在页面中使用<form>表单:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/userinfo/" method="post">
<p>姓名:<input type="text" name="username"></p>
<p>性别:<input type="text" name="sex"></p>
<p>邮箱:<input type="text" name="email"></p>
<p><input type="submit" value="提交"></p>
</form>
</body>
</html>
form标签中最重要的属性有:action——指明数据最终提交的路径,实际就是后台urls.py中urlpatterns中path的第一个参数,即资源路径,method——指明数据提交的方法,有get和post。
修改urls.py,增加资源分配路径:
在views.py中增加函数userinfo,处理接收到的数据:
from django.shortcuts import render,HttpResponse
from pathlib import Path
import os
import datetime
# Create your views here.
def cur_time(request):
base_p = Path(__file__).resolve().parent.parent
templates = os.path.join(base_p, 'templates')
print(templates)
times = datetime.datetime.now()
return render(request,"cur_time.html",{"abc":times})
# 这里使用render来返回一个经过渲染的模板文件,这里就是cur_time.html
# 这里cur_time.html是保存在templates目录中,可以直接写文件名
# Django能够直接找到这个文件,是因为在settings.py配置文件中已经对相关目录进行了配置
# 注意settings.py中TEMPLATES的设置,函数中的base_p和templates就是settings.py中的BASE_DIR和TEMPLATES
userlist = [] # 用于存储客户端提交的用户信息
def userinfo(req):
if req.method == "POST": # 需要按照提交方法进行不同处理,这里是POST提交时执行
username = req.POST.get("username",None)
sex = req.POST.get("sex", None)
email = req.POST.get("email", None)
user = {"username":username,"sex":sex,"email":email}
userlist.append(user)
print("username:",username)
print("sex:",sex)
print("email:",email)
return render(req,"userinfo.html",{"userlist":userlist})
# 这里传递了字典参数,也可以叫他用户数据,经过了渲染,所以,userinfo.html在这里不是页面文件,而是模板文件
else: # 如果不是POST方法提交,执行这里,这里的userinfo.html也是模板文件,也要经过渲染,只不过这里没有第三个参数,所以渲染有可能只用到了request中的数据。
return render(req,"userinfo.html")
# 所以,对于render方法,其中的.html文件都是模板。
因为传递了userlist字典参数,前端要获取,需要render进行渲染,将数据嵌入进去,修改userinfo.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/userinfo/" method="post">
<p>姓名:<input type="text" name="username"></p>
<p>性别:<input type="text" name="sex"></p>
<p>邮箱:<input type="text" name="email"></p>
<p><input type="submit" value="提交"></p>
</form>
<hr>
<table border="1px">
<tr>
<td>姓名</td>
<td>性别</td>
<td>邮箱</td>
</tr>
{% for item in userlist %}
<tr>
<td>{{ item.username }}</td>
<td>{{ item.sex }}</td>
<td>{{ item.email }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
{% %}和{{ }}是模板语言的语法,模板被渲染后,才会成为页面文件,发送给前端,前端,即浏览器再进行展现。
这里要注意的是模板中的userlist对应的是render()方法第三个参数,即字典参数的key,如果将render修改为:render(request,“userinfo.html”,{“abc”:userlist}),则模板中{% for item in abc
需要注意的问题:
action=“/userinfo/”要写上最后的斜杠,否则会出现错误:
即对于post方法提交,URL需要在最后加上斜杠"/",或者在settings.py中设置APPEND_SLASH=False(这个方法测试后不好用)
另一个问题是提交时会出现:
这需要在settings中禁用:
这是一个安全设置 。
运行结果:
与数据库关联操作,引入数据库,即引入model层:
就上面的例子,我们添加的用户信息是保存在一个变量userlist列表中,如果系统重启,所有数据丢失,现在把数据保存在数据库中,确保数据永久保存。
引入数据库
首先需要在settings中配置数据库,如下图:
默认数据使用的是sqlite3数据库,数据库名称是db.sqlite3
第二步:在models.py中定义一个类,这个类对应了数据库中的一个数据表:
# models.py
from django.db import models
# Create your models here.
class UserInfo(models.Model):
username = models.CharField(max_length=64)
sex = models.CharField(max_length=12)
email = models.CharField(max_length=64)
第三步,创建了这个类后,需要在终端命令窗口执行一个命令,由这个类在数据库系统中创建对应的表,命令为:python manage.py migrate
双击左边的db.sqlite3,显示图如下:
先执行:
python manage.py makemigrations:这句话的意思是先生成一个迁移,即先生成一个方案
然后再执行迁移:python manage.py migrate
此时,我们定义的model类UserInfo在数据库中生成了对应的表,表名称是应用名_类名
这就是ORM,对象关系模型。
第四步、修改views.py中的userinfo函数,使用数据库进行数据操作
from django.shortcuts import render,HttpResponse
from app01 import models
# Create your views here.
userlist = []
def userinfo(req):
if req.method == "POST":
u = req.POST.get("username",None)
s = req.POST.get("sex", None)
e = req.POST.get("email", None)
# user = {"username":username,"sex":sex,"email":email}
# userlist.append(user)
models.UserInfo.objects.create( #这就是将数据保存到数据库,即数据插入数据库
username=u,
sex=s,
email=e
)
userlist = models.UserInfo.objects.all() # 从数据库取所有数据
return render(req,"userinfo.html",{"userlist":userlist})
# else:
# return render(req,"userinfo.html")
至此,Django从前端到后端,从路径分配到不同路径处理,再到数据库操作和模板渲染,整个MTV过程全部实现。