MVC 模式(Model–view–controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。
除了以上三层之外,还需要一个 URL 分发器,它的作用是将一个个 URL 的页面请求分发给不同的 View 处理,View 再调用相应的 Model 和 Template,MTV 的响应模式如下所示:
django-admin startproject case? ? -- 创建case项目
在项目的根目录下创建一个templates目录,该目录用于存放这个项目共用的模板文件
?接下来要去告诉该django项目我们的模板目录所在的路径,往?case/settings.py 内 TEMPLATES 变量内的 DIRS 的列表内插入模板所在的路径
?BASE_DIR 变量存放的是当前项目所在的路径,加个"templates"为项目下的那个模板目录名
!!然后!!就可以往 templates 目录内加入自己想要的模板文件了。
python manage.py startapp index? -- 在命令行项目目录下输入,创建一个项目业务分支的app
?
?创建完成后要将该app加入到 case/settings.py 下的 INSTALLED_APPS 列表内,告诉该django项目,项目里有一个名为 index 的业务分支app
然后在 index 目录下新建一个 urls.py 文件 ,其主要用途在于,接收 项目下的 urls.py (case/case/urls.py) 发过来的路由寻址请求,因为用户寻址请求会发到项目下的 urls.py 内,在由该文件分发给其他分支业务项目(子项目)下的 urls.py 文件进行处理。
先来介绍下快速响应请求的 HttpResponse 模块
在 case/case/urls.py 内输入以下内容:
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls), # 创建项目时自带的后台登陆路由网址
path('',include(("index.urls","index"),namespace='index')),
# '' 号为空网址(首页),当有include时就会将此行替换为include内指定的文件内的代码内容,,又或者可以说是当path内网址为 '' 又有include时,当前该urls.py 文件就会将本次的路由寻址请求发送给include内指定的业务分支(子项目)下的urls.py进行处理,,,,当网址不为空,且有include时就会报错。。如果指定的include文件内也没有对应的网址就交给下一个进行处理,都没有就响应404错误
]
在 case/index/urls.py 内输入以下内容:
# -*- coding: UTF-8 -*-
from django.urls import path
from . import views
urlpatterns = [
path('',views.index), # 当访问的地址是 '' 网页首页时,就会调用views.index来响应本次请求
]
在case/index/views.py 内新建一个 index 函数,用来处理响应本次请求:
from django.http import HttpResponse
def index(request):
return HttpResponse("hello ")
# HttpResponse 方法可将其内的信息直接当成响应数据,用来响应本次请求
然后在项目根目录的命令行内输入:python manage.py runserver ip:端口? # 运行服务器--可指定ip端口--默认为127.0.0.1:8000
!!! 小提示 !!! 项目运行后,项目中如果代码有改动,服务器会自动监测代码的改动并自动重新载入,所以如果你已经启动了服务器则不需手动重启。
然后访问自己指定的网址,默认为?http://127.0.0.1:8000/
就可以获得响应数据了。
接下来,来介绍下 模板文件 的使用案例
在 case/templates/ 下新建一个?index.html 模板文件?
内容为:
?双引号为声明一个变量的作用,在此处声明一个 hello 变量,后面可以在view.py内传递给该变量,值?。
然后在 case/index/views.py 内新建一个函数,内容为:
from django.shortcuts import render
''' 该模块作用为,将指定的字典内容(字典内的键必须为模板内变量的名字,值则为要给其赋的值)
填充到指定的模板内对应的变量名上。。然后将其响应给用户。。'''
def index(request):
context = {} # 创建一个字典文件,用于存放模板文件内变量的名称,和要给其赋的值
context['hello'] = '我是 index.html 模板的变量的值'
# 字典中元素的键值 hello 对应了模板中的变量 {{ hello }}。
return render(request, 'index.html', context)
修改 case/case/urls.py?文件内容:
?该行代码用于转发此行代码上没有被处理的路由寻址请求给指定的分支业务(子项目)进行处理。
修改case/index/urls.py 文件内容:
当用户访问 index/ 时,因为case/case/urls.py 文件没有该项网址,所以转发请求将本次寻址发给 case/index/urls.py 处理,而case/index/urls.py 有其要的路由地址,然后就调用其的视图函数进行返回响应。
然后在项目根目录的命令行内输入:python manage.py runserver ip:端口? # 运行服务器--可指定ip端口--默认为127.0.0.1:8000
然后访问自己指定的网址,默认为?http://127.0.0.1:8000/index/
就可以获得响应数据了。
这样我们就完成了使用模板来输出数据,从而实现数据与视图分离。具体介绍模板中常用的语法规则见??django-html 模板语法规则介绍
静态文件配置:static
1、在项目的根目录下创建一个 statics 目录文件
2、在 settings 文件的最下方配置添加以下配置:
STATIC_URL = '/static/' # 别名
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "statics"), # 告诉 django 我们的静态目录在哪
]
?3、在 statics 目录下创建 css 目录,js 目录,images 目录,plugins 目录, 分别放 css文件,js文件,图片,插件。
然后在images目录下放入一张照片,方便一会使用
4、在使用的模板文件内插入以下代码:
{% load static %} -- 使用静态文件时,需要先在模板内载入静态文件,
<img src="{% static 'images/picture.png' %}" alt="the a picture">
?5、修改 case/index/views.py 内容:
from django.shortcuts import render
def index(request):
return render(request, "index.html")
然后访问自己指定的网址,默认为?http://127.0.0.1:8000/index/
?就可以显示出插入的图片了。
模板继承:模板可以用继承的方式来实现复用,减少冗余内容。
{% block 名称 %}
在父模板内插入 block -- endblock 的作用是:
父模板开放,可以让继承的子模版自由修改的部分。
在子模版继承父模板后 可以在子模版内 插入 {% block 名称 %} 标签,
然后在 {% block 名称 %} 标签和 {% endblock 名称 %}标签 内自由添加自己的内容
{% endblock 名称 %}
{% extends "父模板路径及名称"%} -- 通过此标签可以让子模版继承指定的父模板
1、在模板文件内创建一个父模板文件
?
插入代码到body标签内:
<body>
<p>我是父模块的代码</p>
{% block mainbody %} -- 开放一个区域让子模版可以自由操纵
<p>父模块开放让子模块可以修改的部分</p>
{% endblock %} -- 结束开放的区域
</body>
2、在子模版中继承父模板:
{%extends "father.html" %} -- 继承 father.html 这个父模板
{% block mainbody %} -- 调用父模板内的 block 标签进行替换父模板提供可替换的部分
<p> block 以下是父模块开放让子模块可以自由修改的部分</p>
<h6> 在 endblock 结束可修改的代码块之前,都可以在里面添加自己想要的内容 </h6>
{% endblock %} -- 结束可替换部分
3、views.py 文件响应子模版。
django -- 模型(ORM):
ORM 为 python 代码和数据库之间的桥梁,python 代码通过 ORM 将代码转化为 SQL 语句,再由pymysql传送到数据库内。
ORM对应数据库的关系对应表:
Django 提供了对 PostgreSQL、MySQL、SQLite、Oracle。数据库的支持。
接下来主要介绍 MySQL 数据库的设置。先下载mysql驱动
下载 pymysql 模块,该模块会将SQL语句通过 pymysql 传送到数据库服务端,在数据库中执行 SQL 语句并将结果返回。
因为ORM 无法操作到数据库级别,只能操作到数据表,所以先创建一个数据库:
create database testmysql default charset=utf8; # 防止编码问题,指定为 utf8
创建了一个名为 testmysql 的数据库后,就将该数据库的信息填入到项目里的?settings.py 文件的?DATABASES 中,告诉django项目我们要连接的数据库。
接下来,告诉 Django 使用 pymysql 模块连接 mysql 数据库:?
# 在与 settings.py 同级目录下的 __init__.py 中引入模块和进行配置
import pymysql
pymysql.install_as_MySQLdb()
django规定,模型必须在分支业务(子项目)内才能使用。所以到分支业务app case/index/models.py 内进行操作:
from django.db import models
class Test(models.Model): # 创建一个名为 Test 的表,
name = models.CharField(max_length=20) # 往这个表内键入一个 name 字段,最大长度为 20 个字符
django中创建字段,默认会创建一个id字段
然后在项目根目录的命令行下输入:
将对models.py文件的设置内容迁移到migrations目录下,一个类对应要生成的一个表
?将migrations目录下新生成的文件在数据库中执行生成其设置的字段信息的表
然后在 case/index/ 新建一个 sql.py 文件。该文件主要用于处理sql请求。内容为:
# -*- coding: UTF-8 -*-
from django.http import HttpResponse # 导入该模块告诉用户说数据添加成功
from .models import Test # 导入数据表对象
# 数据库操作
def testdb(request):
test1 = Test(name='数据一') # 往 Test 数据表中的 name 字段中插入信息
test1.save() # 执行sql语句
return HttpResponse("<p>数据添加成功!</p>") # 告诉用户数据添加成功
修改 case/index/urls.py 内的代码:
# -*- coding: UTF-8 -*-
from django.urls import path
from . import views,sql
urlpatterns = [
path('index/',views.index),
path('testdb/',sql.testdb), # 当有人访问该网址时就调用sql内的testdb返回响应
]
访问 http://127.0.0.1/testdb/
到mysql中查看:testmysql下的index_test表下的字段内容信息。
获取数据:Django提供了多种方式来获取数据库的内容,如下代码所示:
# 通过objects这个模型管理器的all()获得所有数据行,相当于SQL中的 -- select * from 表名;
re1 = Test.objects.all() # 获得这个表的全部信息内容,返回的是列表形式,可通过获取列表值加 .字段名 的方式获取指定字段的内容
# < QuerySet[ < Test: Testobject(1) >, < Test: Testobject(7) >, < Test: Testobject(8) >] >
# filter相当于SQL中的WHERE,可设置条件过滤结果 -- select * from value2 where name = "my one"; //返回value2表下name字段的值为 "my one"的那一行数据
re2 = Test.objects.filter(id=1) # 获取 id 字段为1的那一行数据信息。返回的是列表形式,可通过获取列表值加 .字段名 的方式获取指定字段的内容
# < QuerySet[ < Test: Testobject(1) >] >
# 获取单个对象
re3 = Test.objects.get(id=1) # 获取 id 字段为1的那一行数据信息。返回的是对象。可通过 .字段名 来获取字段内容
# Testobject(1) -
# 限制返回的数据 相当于 SQL 中的 OFFSET 0 LIMIT 2; 切片
re4 = Test.objects.order_by('name')[0:2] # 获取 name 字段前两行的信息内容。返回的是列表形式,可通过获取列表值加 .字段名 的方式获取指定字段的内容
# < QuerySet[ < Test: Testobject(1) >, < Test: Testobject(8) >] >
# 数据排序
re5 = Test.objects.order_by("name") # 获取的是按指定字段进行排序后的所有行信息。从小到大。返回的是列表形式,可通过获取列表值加 .字段名 的方式获取指定字段的内容
# < QuerySet[ < Test: Testobject(1) >, < Test: Testobject(7) >, < Test: Testobject(8) >] >
# 上面的方法可以连锁使用 :获取name字段内容为1的数据,在以id为序列进行排序。返回的是列表形式,可通过获取列表值加 .字段名 的方式获取指定字段的内容
re6 = Test.objects.filter(name='1').order_by("id") # 连续使用筛选出符合条件的数据行。
# < QuerySet[ < Test: Testobject(1) >, < Test: Testobject(8) >] >
?更新/修改字段数据:
# 修改其中一个id=1的name字段,再save,相当于SQL中的 update admin set pass="ad" where id = 1; // 修改admin表内id字段为 1 的那行数据内的pass的值
test1 = Test.objects.get(id=1)
test1.name = 'Google' # 获取id为1的那行数据返回对象形式,将其指定字段名的内容改为 'Google'
test1.save() # 传入SQL 内执行SQL语句
# 另外一种方式
Test.objects.filter(id=2).update(name='Google') # 获取id=2,的数据行,将其的name字段内容改为指定内容
# 修改所有的列
Test.objects.all().update(name='Google') # 获取所有行数据。修改他们的name字段内容为指定内容
删除数据:
# 删除id=1的数据
test1 = Test.objects.get(id=1) # 获取id=1的数据
test1.delete() # 将其删除
# 另外一种方式
# Test.objects.filter(id=1).delete() # 获取id=1的数据将其删除
# 删除所有数据
# Test.objects.all().delete() # 获取所有数据行,并将其删除
?django表单:
HTML表单是网站交互性的经典方式。 本段将介绍如何用Django对用户提交的表单数据进行处理。
HTTP协议以"请求-回复"的方式工作。客户发送请求时,可以在请求中附加数据。服务器通过解析请求,就可以获得客户传来的数据,并根据URL来提供特定的服务。
GET 方法
在 case/index/ 新建一个 form.py 文件。用于接收用户提交的表单的请求和处理。并输入代码:
# -*- coding: UTF-8 -*-
from django.http import HttpResponse
from django.shortcuts import render
# 表单
def search_form(request): # 将表单模板响应给用户
return render(request, 'search_form.html')
# 接收请求数据
def search(request):
request.encoding = 'utf-8' # 将请求的编码改为 utf-8
'''判断用户是否提交了表单模板,因为表单模板的name为 q 所以只需要判断 q 这个表单在不在用户提交的请求里面,
和获取 q 这个信息判断其是不是为空,当其为空,或不在请求里,就返回提交空的表单,否则就将其搜索的内容响应给他'''
if 'q' in request.GET and request.GET['q']:
message = '你搜索的内容为: ' + request.GET['q']
else:
message = '你提交了空表单'
return HttpResponse(message)
在模板目录 templates 中添加 search_form.html 表单:内容为:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> - </title>
</head>
<body>
<form action="/search/" method="get"> -- action=当提交表单时将表单提交给 网址/search/ 路由解析,method=请求方式,有 get post 等等
<input type="text" name="q"> -- 创建一个文本输入框,它的名字为 q ,可用这个名字来获取其输入的内容
<input type="submit" value="搜索"> -- 创建一个提交框,他的按钮名字为 搜索,当点击搜索时会将表单进行提交
</form>
</body>
</html>
往 case/index/urls.py 路由内加入路由网址:
from django.urls import path
from . import search
urlpatterns = [
path('search-form/',search.search_form), # 访问这个路由时,将表单响应回去
path('search/',search.search), # 当表单进行提交时,会寻址这个路由,将调用这个路由设置的方法响应回去
]
访问地址?http://127.0.0.1:8000/search-form/?并搜索,结果如下所示:
POST 方法
先修改 case/index/search.py 文件内容:
from django.shortcuts import render
from django.views.decorators import csrf # 用于防伪判断的模块
# 接收POST请求数据
def search_post(request):
ctx = {} # 创建一个字典用于存放要传给模板内变量的值
if request.POST: # 判断,当请求不为空时,
ctx['rlt'] = request.POST['q'] # 插入一个key为rlt(模板内的变量名),值为,表单q输入的内容
return render(request, "post.html", ctx) # 将值传递到post.html模板内的变量中,响应给用户
在模板目录内创建一个 post.html 表单文件:内容为:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> - </title>
</head>
<body>
<form action="/search-post/" method="post"> -- action=当提交表单时将表单提交给 网址/search-post/ 路由解析,method=请求方式,有 get post 等等
{% csrf_token %} -- 这是 Django 提供的防止伪装提交请求的功能。POST 方法提交的表格,必须有此标签。
<input type="text" name="q"> -- 创建一个文本输入框,它的名字为 q ,可用这个名字来获取其输入的内容
<input type="submit" value="搜索"> -- 创建一个提交框,他的按钮名字为 搜索,当点击搜索时会将表单进行提交
</form>
<p>{{ rlt }}</p> -- 添加一个标签变量,用于获取post请求后将请求内容响应给该标签
</body>
</html>
表格中 {% csrf_token %}?标签。csrf 全称是 Cross Site Request Forgery。这是 Django 提供的防止伪装提交请求的功能。POST 方法提交的表格,必须有此标签。
往 case/index/urls.py 路由内加入路由网址:
from django.urls import path
from . import search
urlpatterns = [
path('search-post/',search.search_post), # 访问这个路由时,将调用设定的方法进行返回
]
访问地址?http://127.0.0.1:8000/search-form/?并搜索,结果如下所示:
django视图:
一个视图函数,简称视图,是一个简单的 Python 函数,它接受 Web 请求并且返回 Web 响应。
响应可以是一个 HTML 页面、一个 404 错误页面、重定向页面、XML 文档、或者一张图片...
无论视图本身包含什么逻辑,都要返回响应。代码写在哪里都可以,只要在 Python 目录下面,一般放在项目的 views.py 文件中。
每个视图函数都负责返回一个 HttpResponse 对象,对象中包含生成的响应。
视图层中有两个重要的对象:请求对象(request)与响应对象(HttpResponse)
请求对象: HttpRequest 对象(简称 request 对象)
以下介绍几个常用的 request 属性。
1、GET
数据类型是 QueryDict,一个类似于字典的对象,包含 HTTP GET 的所有参数。
有相同的键,就把所有的值放到对应的列表里。
取值格式:对象.方法。
get():返回字符串,如果该键对应有多个值,取出该键的最后一个值。
实例:
path('get/',views.get), # 将这句话加入到 case/index/urls.py 路由处理文件中
?case/index/views.py 代码为:
from django.http import HttpResponse
def get(request):
name = request.GET.get('name') # 获取 get 请求中名为 name 的值
return HttpResponse('name:{}'.format(name)) # 并将其响应给用户
访问 get/ 请求时可在其后面加入?并在?后面传入你要传递的get参数。?
2、POST
数据类型是 QueryDict,一个类似于字典的对象,包含 HTTP POST 的所有参数。
常用于 form 表单,form 表单里的标签 name 属性对应参数的键,value 属性对应参数的值。
取值格式:?对象.方法。
get():返回字符串,如果该键对应有多个值,取出该键的最后一个值。
实例:
修改post.html模板文件,内容为:
<form action="/form-post/" method="post"> -- action=当提交表单时将表单提交给 /form -post/ 路由解析,method=请求方式,有 get post 等等
{% csrf_token %} -- 这是 Django 提供的防止伪装提交请求的功能。POST 方法提交的表格,必须有此标签。
<input type="text" name="q"> -- 创建一个文本输入框,它的名字为 q ,可用这个名字来获取其输入的内容
<input type="submit" value="搜索"> -- 创建一个提交框,他的按钮名字为 搜索,当点击搜索时会将表单进行提交
</form>
<p>{{ rlt }}</p> -- 添加一个标签变量,用于获取post请求后将请求内容响应给该标签
在 case/index/urls.py 内插入两个路由:
path('post/',views.post), # 路由寻址,调用指定函数方法,处理响应请求
path('form-post/',views.form_post),
将以下代码插入到 case/index/views.py 中:
def post(request):
return render(request,'post.html') # 触发该函数将会将指定的模板文件响应给用户
def form_post(request):
name = request.POST.get('q') # 触发该函数将会,获取post内q的值,再将 q 的值传到post.html的模板中的指定变量中,
return render(request,'post.html',{'rlt':name}) # 然后将其响应给用户
3.path
调用该方法会获取请求的寻址信息,数据类型时字符串。
def index(request):
name = request.path
print(name) # 访问的是 http://127.0.0.1/index/ 路由。获取的path则是 /index/
return HttpResponse("---")
4、method
获取当前请求使用的方式,GET , POST 等。
def index(request):
name = request.method
print(name) # 获取本次请求使用的是什么请求方式(GET , POST),结果为字符串形式,大写的。
return HttpResponse("菜鸟教程")
5、其他
request 中还有很多好用的方法,比如:
print(request.COOKIES) # 获取本次请求的 cookies 信息
等等等等。详情见 https://www.runoob.com/django/django-form.html 中的 django表单
path的参数:
path('index/',views.index,name='index'),
第一个参数:index/ : 为这行代码的路由地址。可以通过寻址这个路由地址从而完成指定的响应处理
第二个参数:views.index : 当路由寻址为第一个参数时,就会调用该模块内的方法进行处理本次请求,然后进行响应本次请求。
第三个参数:name='index' : 给这个路由地址起一个名字。当有人调用这个名字时,就会把这个路由地址返回给对方
响应对象:
响应对象主要有三种形式:HttpResponse()、render()、redirect()。
HttpResponse():?将文本内容响应给用户。如果字符串里含有 html 标签,也可以渲染。
return HttpResponse("<a href='https://www.baidu.com/'>点击跳转到百度页面</a>")
render():?该方法一共有三个参数:
第一个参数为request(携带用户请求信息进行响应)。如:
第二个参数为字符串格式的,指定的模板文件(*.html)。如:
第三个参数为字典(可选参数,向模板文件传递参数:键为模板文件的参数名,值为要给其赋的值)。
return render(request,"index.html",{"name":'姓名'}) # 将name的值传到 index.html 模板中进行填充。然后将填充后的模板文件响应给用户。
redirect():重定向,跳转新页面。参数为字符串,字符串中填写 路由寻址路径 。一般用于 form 表单提交后,跳转到新页面。如:
return redirect("/index/") # 将会将该 /index/ 响应给用户,然后相当于用户访问了,http://127.0.0.1/index/ 一样,然后继续继续路由寻址操作
django-admin startproject name ?# 在自定路径命令行下输入--创建一个名为name的项目
python manage.py startapp branch ?# 在name项目下生成一个branch分支业务的app
? ? - 创建分支业务后需在项目下的settings.py-->INSTALLED_APPS 中加入你的应用名字进行注册安装
python manage.py makemigrations ?# 将对models.py文件的设置内容迁移到migrations目录下,一个类对应要生成的一个表
python manage.py migrate ? # 将内置的迁移文件生成数据表--将migrations目录下新生成的文件在数据库中执行生成其设置字段信息的表
python manage.py runserver ip:端口 ?# 在name项目下输入--运行服务器--可指定ip端口--默认为127.0.0.1:8000
python manage.py createsuperuser ?# 创建管理员命令