Django是一个开放源代码的Web应用框架,由Python写成。采用了MTV的框架模式,即模型M,视图V和模版T。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。并于2005年7月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的。 -- 百度百科
本文章只是学习笔记,部分资料参考自互联网,图片非原创,仅用于学习理解 !
MVC 与 MTV
MVC - Model View Controller,模型(model)-视图(view)-控制器(controller)的缩写,是软件工程中的一种软件架构模式,Model模型中主要用于存储与数据库相关的字段或数据库通信方面的东西,Controller控制器用于存储URL的分发等,最后的View视图则是完善控制器中的路径分发,每一个路径对应一个view视图函数。
模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起:
A.模型负责业务对象与数据库的映射(ORM)
B.视图负责与用户的交互(页面)
C.控制器接受用户的输入调用模型和视图完成用户的请求
ORM:对象关系映射(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping)
通常情况下我们写代码用的是面向对象的方法,而我们的数据库无法支持面向对象的编程,为了解决两者之间的不同,就出现了ORM映射技术,使用这种技术我们无需关注sql语句的具体编写,只需要使用特定的API即可完成复杂的查询删除等任务,但有一个缺点,采用此技术在一定程度上会消耗系统部分资源,而对于非常复杂的查询工作,还是要使用纯SQL语句来写。
Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是值:
M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
T 代表模板 (Template):负责如何把页面展示给用户(html)。
V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。
除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:
这种设计模式优势在于各组件都是松耦合的。每个由Django驱动的Web应用都有着明确的目的,并且可独立更改而不影响到其它的部分。
HTTP协议:Hyper Text Transfer Protocol(超文本传输协议),是用于万维网服务器与本地浏览器之间传输超文本的传送协议。
该协议是基于TCP/IP的请求协议
HTTP协议规定,请求从客户端发出,最后服务器端响应该请求并 返回。换句话说,肯定是先从客户端开始建立通信的,服务器端在没有 接收到请求之前不会发送响应无状态保存
HTTP是一种不保存状态,即无状态(stateless)协议。HTTP协议自身不对请求和响应之间的通信状态进行保存,协议对于发送过的请求或响应都不做持久化处理。
无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
HTTP请求方式
GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,POST方法是把提交的数据放在HTTP包的Body中.
GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
GET与POST请求在服务端获取请求数据方式不同。
GET方式提交数据,会带来安全问题,而POST请求则相对安全。
Django 作者
创建第一个django项目
1.如果是使用Pycharm创建的项目,直接创建项目,即可。
2.如果没有创建app的名字,也可以在进入django目录中,执行 python manage.py startapp MyWeb 命令创建.
更多django shell命令行参数。
python manage.py shell #进入django shell
python manage.py dbshell #进入django dbshell
python manage.py check #检查django项目完整性
python manage.py flush #清空数据库
python manage.py compilemessages #编译语言文件
python manage.py makemessages #创建语言文件
python manage.py showmigrations #查看生成的数据库同步脚本
python manage.py sqlflush #查看生成清空数据库的脚本
python manage.py sqlmigrate #查看数据库同步的sql语句
python manage.py dumpdata #导出数据
python manage.py loaddata #导入数据
python manage.py diffsettings #查看你的配置和django默认配置的不同之处
2.修改settings.py 配置文件,导入我们的app的名字,去掉csrf这个选项
MIDDLEWARE = [
'django.middleware.csrf.CsrfViewMiddleware', # 为了能够开心玩耍,把这个干掉
]
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'MyWeb.apps.MywebConfig' # 导入
]
3.来urls.py里面写一条路由,名字就叫hello , 映射到views.hello函数下处理此请求。
from MyWeb import views # 导入
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/',views.hello)
]
4.最后在myweb里面的views.py设置一个视图函数,最后运行。
from django.shortcuts import HttpResponse
# Create your views here.
# 这个request必须加,不然会报错
def hello(request):
return HttpResponse("<h1>hello lyshark</h1>")
5.配置好以后,启动django,访问 http://127.0.0.1:8000/ 完成了。
6.如果需要引入静态资源,需要设置一下settings.py
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
# 这个路径是对应 src="/static/ 的别名
# 如果这个路径改为 STATIC_URL = '/abc/' 那么<script src="/abc/xxx.js"></script>
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)
Django 基本使用
初始化Django
D:> pip install django # 安装
D:> django-admin startproject MyProject # 创建项目
D:MyProject> django-admin startapp MyWeb # 创建APP
D:MyProject> python manage.py runserver 0.0.0.0:80 # 启动Django
D:MyProject> python manage.py shell # 进入Django交互shell
D:MyProject> python manage.py dbshell # 进入DBShell
D:MyProject> python manage.py check # 检查Django完整性
修改一下django的配置文件settings.py
,导入我们生成APP的名字.
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
#'django.middleware.csrf.CsrfViewMiddleware', # 注释掉此行
'django.contrib.auth.middleware.AuthenticationMiddleware',
]
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'MyWeb.apps.MywebConfig' # 添加此行,导入我们的APP的名字
]
然会修改urls.py
在这里写一条路由记录.
from MyWeb import views
urlpatterns = [
path('admin/', admin.site.urls),
path("hello/",views.hello,name="hello")
]
最后我们在views.py
视图函数里添加一条路由.
from django.shortcuts import HttpResponse
def hello(request):
return HttpResponse("<h1>hello lyshark</h1>")
有时候我们需要在本地引入JS或者静态资源,此时你需要修改一下Django的setting.py
里面的路径.
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
# 此时我们的默认路径是/static/,那么前端就可以直接调用<script src="/static/lyshark.js">
STATIC_URL = '/static/'
STATICFILES_DIRS=(
os.path.join(BASE_DIR,'static')
)
Django 模板与视图
简单的路由编写
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.index,name="index"), # 一条访问主站的路由
path('login/id=<int:id>&name=<str:name>',views.login,name="login"), # 名称后面传递参数
path('add/<int:x>/<int:y>/',views.add,name="add") # 路径中传递参数
]
from django.shortcuts import render,HttpResponse
def index(request):
return render(request,"index.html")
def login(request, id, name):
return HttpResponse("用户ID{} , 用户名{} ".format(id,name))
def add(request,x,y):
temp = int(x)+int(y)
return HttpResponse("相加结果:{}".format(temp))
使用模板传递简单的参数
<b>用户名: {{ user }} 密码:{{ pasd }} 标题:{{ title }}</b>
def index(request):
username = "lyshark"
password = "123123"
title = "hello lyshark"
return render(request,"index.html",{"user":username,"pasd":password,"title":title})
后端组装数据然后传递给前端
<b>用户名: {{ user }} 密码:{{ pasd }} 标题:{{ title }}</b>
def index(request):
username = "admin"
password = "123123"
title = "hello lyshark"
dict = {
"user": username,
"pasd": password,
"title": title
}
return render(request,"index.html",dict)
通过info变量遍历出指定字段元素
<b>站点名称:{{ info.site }} 站点描述:{{ info.content }}</b>
def index(request):
info = {"site":"blib.cn","content":"hello lyshark"}
return render(request,"index.html",{"info":info})
通过for语句遍历打印列表数据
{% for item in total %}
<b>打印数据: {{ item }}</b><br>
{% endfor %}
def index(request):
lists = ["HTML","CSS","JAVASCRIPT","Python","JQuery"]
return render(request,"index.html",{"total":lists})
通过for语句倒序循环打印
{% for item in total reversed%}
<b>打印数据: {{ item }}</b><br>
{% endfor %}
def index(request):
lists = ["1","2","3","4","5"]
return render(request,"index.html",{"total":lists})
通过使用for循环遍历字典
{% for key,value in info.items %}
{{ key }} : {{ value }}
{% endfor %}
def index(request):
info = {"site":"blib.cn","content":"hello lyshark"}
info1 = {"site": "blib.cn", "content": "hello admin"}
return render(request,"index.html",{"info":info,"info1":info1})
简单的路径拼接
<a href="{{ request.path }}?uid=1">当前网址加参数</a>
<!--获取当前路径 拼接成 /add/4/5-->
{{ request.path }}{% url 'add' 4 5 %}
def add(request,x,y):
temp = int(x)+int(y)
return HttpResponse("相加结果:{}".format(temp))
def index(request):
return render(request,"index.html")
判断用户是否登录
{% if request.user.is_authenticated %}
{{ request.user.username }},您好!
{% else %}
请登陆,这里放登陆链接
{% endif %}
使用if语句判断数据
{% if username == "lyshark" and password == "123123" %}
<b>恭喜你</b>
{% elif username == "admin" or password == "123123" %}
<b>欢迎管理员</b>
{% else %}
<b>这个都不是</b>
{% endif %}
def index(request):
username = "admin"
password = "123123"
return render(request,"index.html",{"username":username,"password":password})
if语句也可以判断列表元素
{% if 1 in list %}
<b>在里面</b>
{% elif 10 not in list %}
<b> 不在里面</b>
{% endif %}
def index(request):
list = [1,2,3,4,5]
return render(request,"index.html",{"list":list})
最后的大总结:if与for语句的结合
{% for item in info %}
{% if forloop.first %}
<b>开始了</b>
{% endif %}
{{ forloop.counter }} : {{ item }}<br>
{% if forloop.last %}
<b>最后了</b>
{% endif %}
{% endfor %}
def index(request):
list = map(str,range(100))
return render(request,"index.html",{"info":list})
forloop.counter 索引从 1 开始算
forloop.counter0 索引从 0 开始算
forloop.revcounter 索引从最大长度到 1
forloop.revcounter0 索引从最大长度到 0
forloop.first 当遍历的元素为第一项时为真
forloop.last 当遍历的元素为最后一项时为真
forloop.parentloop
用在嵌套的 for 循环中,获取上一层 for 循环的 forloop
常用的过滤器: 常用的过滤器,有以下几种.
<b> 列表长度: {{ total | length }}</b><br>
<b> 输出大小: {{ size | filesizeformat }}</b><br>
<b> 输出时间: {{ date | date:"Y-m-d" }}</b><br>
<b> 首字母大写: {{ title | capfirst }}</b><br>
<b> 从字符串中移除hello字符: {{title | cut:"hello" }}</b><br>
<b> 显示字符串第一个元素: {{ total | first }}</b><br>
<b> 显示字符串最后一个元素: {{ total | last }}</b><br>
<b> 大小写转换(upper/lower): {{ title | upper }}</b><br>
<b> 对数据切片: {{ title | slice:"2:-1" }}</b><br>
<b>截断字符:{{ title | truncatechars:5 }}</b><br>
<b>截断单词:{{ title | truncatewords:1 }}</b>
def index(request):
filesize = 10240
title = "hello lyshark"
date = datetime.datetime.now()
lists = ["1","2","3","4","5"]
return render(request,"index.html",{"total":lists,"size":filesize,"date":date,"title":title})
自定义过滤器与标签
1.首先在Django项目下的APP里面,创建一个templatetags
的目录,这个目录名不能变.
MyWeb/
__init__.py
models.py
templatetags/
__init__.py
mysimple.py
views.py
2.在templatetags
目录下创建任意的py文件,此处我们就创建一个mysimple.py
,并写入以下两条内容.
from django import template
from django.utils.safestring import mark_safe
register = template.Library() # 此处必须这样写
# simple_tag(自定义标签):不会限制传参,但不支持if
@register.simple_tag
def simple_time(var1,var2,var3):
temp = int(var1)+int(var2)+int(var3)
return temp
# filter(自定义过滤器):限制传参2个,但支持if
@register.filter
def My_filter(value, arg):
# 传递一个参数的过滤器
return str.upper(value) + arg
3.在我们需要使用自定义过滤器的时候,必须在index.html
中引入这个变量,然后在前端就可以调用了.
# name: views.py
def index(request):
title = "hello"
return render(request,"index.html",{"title":title})
# name: index.html
<!--引入自定义的过滤器-->
{% load mysimple %}
<b>自定义标签返回数值: {% simple_time 10 20 30 %}</b> <!-- 传递多个参数 -->
<b>传递一个参数的过滤器: {{ title | My_filter:'lyshark' }}</b> <!-- 传递一个参数 -->
模板与模板继承
母板: {% block title %}{% endblock %}
子板继承: {% extends "base.html" %}
子板中使用其他模板: {% include "xx.html" %}
设置标题: {% block title %}{% endblock %}
使用CSS资源: {% block css %} {% endblock %}
使用JS资源: {% block js %} {% endblock %}
1.首先创建一个base.html
文件,以作为我们的母版.
<html>
<head>
<meta charset="UTF-8">
{% block css %}{% endblock %}
</head>
<body>
<div class="pg-body">
<div class="body-menu">
<ul>
<li><a href="/user">用户管理</a></li>
<li><a href="/hosts">资产管理</a></li>
</ul>
</div>
<div class="body-content">
{% block body %}{% endblock %} <!--占位符,用于填充子版块-->
</div>
</div>
{% block js %}{% endblock %}
</body>
</html>
接着我们需要创建一个子板并继承母版,此处我们创建一个hosts.html
这样的文件.
{% extends 'base.html' %}
{% block js %} {% endblock %}
{% block css %} {% endblock %}
{% block body %}
<table>
{% for item in host %}
<tr>
<td>{{ item.hostname }}</td>
<td>{{ item.port }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
我们继续创建一个user.html
,同样也是继承base.html
模板.
{% extends 'base.html' %}
{% block js %} {% endblock %}
{% block css %} {% endblock %}
{% block body %}
<ul>
{% for item in user_list %}
<li>{{ item.username }},{{ item.salary }}</li>
{% endfor %}
</ul>
{% endblock %}
此处我们需要在urls.py
里面写好路由分发.
from django.contrib import admin
from django.urls import path
from MyWeb import views
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.index,name="index"),
path('hosts/',views.hosts,name="hosts"),
path('user/',views.userinfo,name="user")
]
然后写好views.py
中的视图函数,默认我们返回base.html
这个页面.
from django.shortcuts import render
from django.shortcuts import HttpResponse
def index(request):
return render(request,"base.html")
def hosts(request):
hosts_list = []
for i in range(10):
temp = {'hostname':'192.168.1.'+str(i),'port':80}
hosts_list.append(temp)
return render(request,'hosts.html',{'host':hosts_list})
def userinfo(request):
user_list = []
for i in range(10):
temp = {'username': 'user' + str(i),'salary':80}
user_list.append(temp)
return render(request,'user.html',{'user_list':user_list})
简单的用户登录
# name:login.html
<!DOCTYPE html>
<body lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<form action="{% url 'login' %}" method="post"> # 通过模板获取到login的试图
<input type="text" name="username" />
<input type="text" name="password" />
<input type="submit" name="提交"/>
</form>
</body>
</html>
# name: urls.py
from django.contrib import admin
from django.urls import path
from MyWeb import views
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', views.login, name="login") # name是给视图起一个名字
]
# name:views.py
from django.shortcuts import render,HttpResponse
def login(request):
if request.method == "GET":
return render(request,"index.html")
elif request.method == "POST":
username = request.POST.get("username")
password = request.POST.get("password")
return HttpResponse("您提交的用户:{} 密码:{}".format(username,password))