Django 是用 Python 写的一个自由和开放源码 web 应用程序框架。
web框架是一套组件,能帮助你更快、更容易地开发web站点。当你开始构建一个web站点时,你总须要一些类似的组件:处理用户认证(注册、登陆、登出)的方式、一个管理站点的面板、表单、上传文件的方式,等等。
有不少人注意到web开发人员会面临一些共同的问题,他们联手建立了 web 框架(Django 是其中一个)来供人使用。框架的存在,你无需从新发明轮子就能创建新的站点。html
在目前基于Python语言的几十个Web开发框架中,几乎全部的全栈框架都强制或引导开发者使用MVC设计模式。所谓全栈框架,是指除了封装网络和线程操做,还提供HTTP、数据库读写管理、HTML模板引擎等一系列功能的Web框架,好比Django、Tornado和Flask。python
最先由Trygve Teenskaug
在1978年提出,上世纪80年代是程序语言Smalltalk的一种内部架构。后来MVC被其余领域借鉴,成为了软件工程中的一种软件架构模式。MVC把Web框架分为3个基础部分:web
模型(Model):用于封装与应用程序的业务逻辑相关的数据及对数据的处理方法,是Web应用程序中用于处理应用程序的数据逻辑的部分,Model只提供功能性的接口,经过这些接口能够获取Model的全部功能。白话说,这个模块就是Web框架和数据库的交互层。sql
视图(View):负责数据的显示和呈现,是对用户的直接输出。数据库
控制器(Controller):负责从用户端收集用户的输入,能够当作提供View的反向功能。django
这三个部分互相独立,但又相互联系,使得改进和升级界面及用户交互流程,在Web开发过程任务分配时,不须要重写业务逻辑及数据访问代码。设计模式
MVC在Python以外的语言中也有普遍应用,例如VC++的MFC,Java的Structs及Spring、C#的.NET开发框架,都很是有名。浏览器
Django对传统的MVC设计模式进行了修改,将视图分红View模块和Template模块两部分,将动态的逻辑处理与静态的页面展示分离开。而Model采用了ORM技术,将关系型数据库表抽象成面向对象的Python类,将表操做转换成类操做,避免了复杂的SQL语句编写。MTV和MVC本质上是同样的。服务器
模型(Model):和MVC中的定义同样网络
模板(Template):将数据与HTML语言结合起来的引擎
视图(View):负责实际的业务逻辑实现
Django的MTV模型组织可参考下图所示:
pip3 install django
打开命令行,cd 到一个你想放置你代码的目录,而后运行如下命令:
django-admin startproject mysite
这行代码将会在当前目录下建立一个 mysite
目录。mysite目录只是你项目的名称, Django 不关心它的名字,能够将它重命名为任何你喜欢的名字。
命令行中CD到你建立的工程中,我这里是mysite目录,输入如下命令
python manage.py runserver
这样建立的网站就开始运行了,django启动默认端口为8000,能够用浏览器访问:http://127.0.0.1:8000/,以下:
这样说明django程序成功运行起来了。
这些文件或目录的做用:
(1)最外层的mysite/目录: 是项目的容器, Django 不关心它的名字,能够将它重命名其余名字。
(2)manage.py: 一个让你用各类方式管理 Django 项目的命令行工具。好比咱们以前用的python manage.py runserver命令。
(3)里面一层的mysite/目录:包含你的项目,它是一个纯 Python 包。它的名字就是当你引用它内部任何东西时须要用到的 Python 包名。 好比 mysite.urls。
(4)mysite/__init__.py: 一个空文件,告诉 Python 这个目录应该被认为是一个 Python 包。
(5)mysite/settings.py:Django 项目的配置文件。后面会详细说到。
(6)mysite/urls.py:Django 项目的 URL 路由系统,就像你网站的“目录”。
(7)mysite/wsgi.py:做为你的项目的运行在 WSGI 兼容的Web服务器上的入口。后面会详细说到。
(8)db.sqlite3 是django默认使用的sqlite3数据库文件。
(1)咱们建立app目录(用于写整个web站点的某种功能),命令以下:
python manage.py startapp app01
(2)编写视图
在app01/views.py 中写以下函数:
from django.http import HttpResponse def index(request): return HttpResponse("Hello, welcome to app01 index.")
(3)在mysite/urls.py中声明一个路由
from django.conf.urls import url from django.contrib import admin from app01 import views # 导入app01的视图 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index', views.index), # 注册index 路由 ]
须要作两点:导入视图,注册路由。 而后咱们重启服务,访问http://127.0.0.1:8000/index/看看:
(1)function based view (FBV)。
像前文那样在app01/views.py 中,写一个函数,处理请求,并返回结果就叫function based view,简称FBV。咱们能够写的详尽些:
app01/views.py中:
from django.http import HttpResponse def home(request): ret = None if request.method == "GET": ret = "Welcome to home." return HttpResponse(ret)
mysite/urls.py中:
from django.conf.urls import url from django.contrib import admin from app01 import views # 导入app01的视图 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^home', views.home), # 注册home 路由 ]
重启以后访问:http://127.0.0.1:8000/home,以下:
注意:视图函数中的request是django对http请求的封装,其中request.method封装了请求动做,包括GET,PUT,POST等。
(2)class based view (CBV)
用类代替视图函数的方法就叫作CBV,写法以下:
app01/views.py中:
from django.http import HttpResponse from django.views import View # 引入该类 # class based view class MyHome(View): # 继承views类 def get(self, request): # get请求会用这个方法处理,若是是post请求再写个post方法处理便可 ret = "Welcome to my home" return HttpResponse(ret)
mysite/urls.py中:
from django.conf.urls import url from app01 import views # 导入app01的视图 urlpatterns = [ # 注册myhome 路由, 方式是views.类名.as_view() url(r'^myhome', views.MyHome.as_view()), ]
启服务以后,访问:http://127.0.0.1:8000/myhome, 以下:
(1)返回html字符串
前文演示了在视图函数中直接返回一些字符串给用户,用的是from django.http import HttpResponse中的HttpResponse对象。
还能够用from django.shortcuts import HttpResponse 的HttpResponse是同样的,咱们稍加改编一下返回的字符串,改为带有HTML标签的字符串看看:
view.py
from django.shortcuts import HttpResponse def index(request): ret = "<h1>{}</h1>".format("Hello, welcome to app01 index.") return HttpResponse(ret)
urls.py
from django.conf.urls import url from app01 import views # 导入app01的视图 urlpatterns = [ url(r'^index', views.index), ]
重启以后,访问http://127.0.0.1:8000/index,以下:
可见,咱们的“<h1></h1>” 标签是生效的,也就是说,若是咱们把一个HTML文件的内容读取成一长串字符串的返回,那么用户就能看到一个完整的网页了。
在Python中,每每把HTML文件统一放在templates目录下。
(2)在项目根目录mysite下新建templates文件夹
3)在django的配置文件mysite/settings.py中找到TEMPLATES这个变量,是一个大列表,在列表中的DIRS后面,配上'templates',便可;即'DIRS': ['templates', ],以下:
(4)接下来能够在templates文件夹下建立一个HTML文件,如index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> <h1>Welcome to mysite index..</h1> <a href="http://www.cnblogs.com/jinyuanliu/">博客链接</a> </body> </html>
(5)在app01/views.py中修改一下视图函数index()
from django.shortcuts import render def index(request): return render(request, "index.html", )
(6)重启后,访问http://127.0.0.1:8000/index
(1)views.py 的index中能够传变量,以下
from django.shortcuts import render def index(request): name = "liuyy" fruits = ["火龙果", "香蕉", "西瓜"] info = { "age": 26, "salary": 1000000, } return render(request, "index.html", {"name": name, "fruits": fruits, "user": info})
(2)传参数以后能够在模板index.html中使用这些参数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> <h1>Welcome to mysite index..</h1> <a href="http://www.cnblogs.com/jinyuanliu/">博客链接</a> <p>我是{{ name }}</p> <p>喜欢的水果有:</p> {% for item in fruits %} <p>水果{{ forloop.counter }}: {{ item }}</p> {% endfor %} {% if "age" not in user %} <p>没有年龄</p> {% else %} <p> 年龄 {{ user.age }}</p> {% endif %} <p> 第二个水果 {{ fruits.1 }}</p> {% for k, v in user.items %} <p>{{ k }}: {{ v }}</p> {% endfor %} </body> </html>
重启以后,访问http://127.0.0.1:8000/index,以下:
总结一下模板语言格式:
# 单个变量{{ name }} # if else 语句 {% if 条件 %} dosth.. {% else %} dosth.. {% endif %} # 遍历item_list {% for item in item_list %} <p>{{ item }}</p> {% endfor %} # 表示第几回循环(从1开始): {{ forloop.counter }} # 若是是第一次循环{{ forloop.first }}为True, 不然为 False # 若是是最后一次循环 {{ forloop.last }} 为True, 不然为False # 遍历字典dic {% for k, v in user.items %} <p>{{ k }}: {{ v }}</p> {% endfor %} # 列表li中的第i个元素: {{ li.i }} # 字典dic中k对应的值: {{ dic.k }} # 使用继承模板: # 母板base.html:{% block title %} {% endblock %} # 子板:{% extends "base.html" %} {% block title %} {% endblock %} # 帮助方法: {{ item.timetype|date:"Y-m-d H:i:s"}} {{ bio|truncatewords:"30" }} {{ my_list|first|upper }} {{ name|lower }}
(1)在app01目录下建立templatetags目录
(2)在templatetags目录下新建任意py文件, 如tag1.py
from django import template from django.utils.safestring import mark_safe register = template.Library() @register.simple_tag def tag_add_3_no(v1, v2, v3): return v1 + v2 + v3 @register.simple_tag def my_input(name): result = "<h1> %s </h1>" % name # mark_safe 会让html标签合法 return mark_safe(result)
其中的两个函数就是本身自定义的函数,想怎么写怎么写。
(3) 哪一个html文件须要引用自定义的simple_tag,须要在html中导入以前建立的py文件
{% load tag1 %}
(4)在html模板中使用simple_tag
{% tag_add_3_no 1 2 3%} {% my_input '个人simpletag'%}
即{% 函数名 参数1 参数2%}
(5)关键一步:在settings.py中配置app
找到settings中的INSTALLED_APPS,注册app01,以下:
若是不注册的话,django没法找到自定义的simple_tag。
(6)完整配置
views.py
from django.shortcuts import render def index(request): return render(request, "index.html")
urls.py
from django.conf.urls import url from app01 import views # 导入app01的视图 urlpatterns = [ url(r'^index', views.index), ]
index.py
{% load tag1 %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> {% tag_add_3_no 1 2 3%} {% my_input '个人simpletag'%} </body> </html>
tag1.py
from django import template from django.utils.safestring import mark_safe register = template.Library() @register.simple_tag def tag_add_3_no(v1, v2, v3): return v1 + v2 + v3 @register.simple_tag def my_input(name): result = "<h1> %s </h1>" % name # mark_safe 会让html标签合法 return mark_safe(result)