传说中的Django

Django由来

  Django是一个开放源代码的Web应用框架,由Python写成。采用了MVC的框架模式,即模型M,视图V和控制器C。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。并于2005年7月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的。Django的作者不是一个人而是一个团队(点击 Django Team了解团队成员),我们都知道Django是以一个人的名字命名的,就是下面这个人,我们就叫他“三指琴魔”强哥吧

Django的设计思路

  Django的主要目标是使得开发复杂的、数据库驱动的网站变得简单。Django注重组件的重用性和“可插拔性”,敏捷开发和DRY法则(Don't Repeat Yourself)。在Django中Python被普遍使用,甚至包括配置文件和数据模型。

Django采用MTV开发模式

  Django是一个基于MVC构造的框架。但是在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),称为 MTV模式。在这种模型之下,我们能够最直接的感受到他的解耦合性,前后端完全分离,它们各自的职责如下:

  • 模型(Model),即数据存取层 处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
  • 视图(View),即表现层 处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
  • 模板(Template),即业务逻辑层 存取模型及调取恰当模板的相关逻辑。模型与模板的桥梁。

Django项目全貌

Django安装配置

Django在终端下安装

  1. # pip3 install django==1.11.11

Django在Pycharm上安装

以Mac os系统为演示标准,如果Windows或者Linux系统的朋友看了本篇文章无法安装的话,请在文章下面留言

进入Pycharm以此选择功能键PYcharm--Preferences--Project--Project Interpreter--(+)--搜索Django,具体如下图所示

Django安装特别提醒

Django有很多版本,建议安装1.11.**的版本,不要安装最新版,不要升级!不要安装最新版,不要升级!不要安装最新版,不要升级!

  1. # 不同版本之间的选择
  2. Django 1.5.x 支持 Python 2.6.5 Python 2.7, Python 3.2 3.3.
  3. Django 1.6.x 支持 Python 2.6.X, 2.7.X, 3.2.X 3.3.X
  4. Django 1.7.x 支持 Python 2.7, 3.2, 3.3, 3.4 (注意:Python 2.6 不支持了)
  5. Django 1.8.x 支持 Python 2.7, 3.2, 3.3, 3.4 3.5. (长期支持版本 LTS)
  6. Django 1.9.x 支持 Python 2.7, 3.4 3.5. 不支持 3.3
  7. Django 1.10.x 支持 Python 2.7, 3.4 3.5.
  8. Django 1.11.x 支持Python3.43.53.6(长期支持版本 LTS)
  9. 下一个长期支持版本,将于2019年发布
  10. 更详细的资料可以到https://www.djangoproject.com/download/请自行查找。
  11. 不同版本的Django在创建相同项目时会有不一样的settings,并且包含有不同的模块,或少或多了某些指令,所以在相同环境下不要安装不同版本的Django,在某版本下创建的项目最好沿用原来的Django版本,以避免冲突。

原因如下

Django实现原理

Django本质上就是一个Web框架

我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。 这样我们就可以自己实现Web框架了。

  1. import socket
  2.  
  3. sk = socket.socket()
  4. sk.bind(("127.0.0.1", 80))
  5. sk.listen()
  6.  
  7. while True:
  8. conn, addr = sk.accept()
  9. data = conn.recv(8096)
  10. conn.send(b"OK")
  11. conn.close()

半成品自定义Web框架

可以说Web服务本质上都是在这十几行代码基础上扩展出来的。这段代码就是它们的祖宗。

用户的浏览器一输入网址,会给服务端发送数据,那浏览器会发送什么数据?怎么发?这个谁来定? 你这个网站是这个规定,他那个网站按照他那个规定,这互联网还能玩么?

所以,必须有一个统一的规则,让大家发送消息、接收消息的时候有个格式依据,不能随便写。

这个规则就是HTTP协议,以后浏览器发送请求信息也好,服务器回复响应信息也罢,都要按照这个规则来。

HTTP协议主要规定了客户端和服务器之间的通信格式,那HTTP协议是怎么规定消息格式的呢?

让我们首先打印下我们在服务端接收到的消息是什么。

  1. import socket
  2.  
  3. sk = socket.socket()
  4. sk.bind(("127.0.0.1", 80))
  5. sk.listen()
  6.  
  7. while True:
  8. conn, addr = sk.accept()
  9. data = conn.recv(8096)
  10. print(data) # 将浏览器发来的消息打印出来
  11. conn.send(b"OK")
  12. conn.close()

服务端

  1. b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nDNT: 1\r\nAccept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=RKBXh1d3M97iz03Rpbojx1bR6mhHudhyX5PszUxxG3bOEwh1lxFpGOgWN93ZH3zv\r\n\r\n'

输出

然后我们再看一下我们访问博客园官网时浏览器收到的响应信息是什么。

响应相关信息可以在浏览器调试窗口的network标签页中看到。

点击view source之后显示如下图:

我们发现收发的消息需要按照一定的格式来,这里就需要了解一下HTTP协议了。

请点击前端入门教程(一)HTTP协议的深刻理解 这篇文章

  经过上面的补充学习,我们知道了要想让我们自己写的web server端正经起来,必须要让我们的Web server在给客户端回复消息的时候按照HTTP协议的规则加上响应状态行,这样我们就实现了一个正经的Web框架了。

  1. import socket
  2.  
  3. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  4. sock.bind(('127.0.0.1', 8000))
  5. sock.listen()
  6.  
  7. while True:
  8. conn, addr = sock.accept()
  9. data = conn.recv(8096)
  10. # 给回复的消息加上响应状态行
  11. conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
  12. conn.send(b"OK")
  13. conn.close()

处男版自定义Web框架

你还可以给他写成函数版,也可以为他赋予动态,不过写框架的路恐怕和西天取经一样久远,我们就到此结束好不

服务器程序和应用程序

  对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

  WSGI(Web Server Gateway Interface)就是一种规范,它定义了使用Python编写的web应用程序与web服务器程序之间的接口格式,实现web应用程序与web服务器程序间的解耦。

常用的WSGI服务器有uwsgi、Gunicorn。而Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器。

继续上面的Web框架。。。

  1. """
  2. 根据URL中不同的路径返回不同的内容--函数进阶版
  3. 返回HTML页面
  4. 让网页动态起来
  5. wsgiref模块版
  6. """
  7.  
  8. import time
  9. from wsgiref.simple_server import make_server
  10.  
  11. # 将返回不同的内容部分封装成函数
  12. def index(url):
  13. with open("index.html", "r", encoding="utf8") as f:
  14. s = f.read()
  15. now = str(time.time())
  16. s = s.replace("@@oo@@", now)
  17. return bytes(s, encoding="utf8")
  18.  
  19. def home(url):
  20. with open("home.html", "r", encoding="utf8") as f:
  21. s = f.read()
  22. return bytes(s, encoding="utf8")
  23.  
  24. # 定义一个url和实际要执行的函数的对应关系
  25. list1 = [
  26. ("/index/", index),
  27. ("/home/", home),
  28. ]
  29.  
  30. def run_server(environ, start_response):
  31. start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # 设置HTTP响应的状态码和头信息
  32. url = environ['PATH_INFO'] # 取到用户输入的url
  33. func = None
  34. for i in list1:
  35. if i[0] == url:
  36. func = i[1]
  37. break
  38. if func:
  39. response = func(url)
  40. else:
  41. response = b"404 not found!"
  42. return [response, ]
  43.  
  44. if __name__ == '__main__':
  45. httpd = make_server('127.0.0.1', 8090, run_server)
  46. print("我在8090等你哦...")
  47. httpd.serve_forever()

wsgiref替换socket server

  上面的代码实现了一个简单的动态,我完全可以从数据库中查询数据,然后去替换我html中的对应内容,然后再发送给浏览器完成渲染。 这个过程就相当于HTML模板渲染数据。 本质上就是HTML内容中利用一些特殊的符号来替换要展示的数据。 我这里用的特殊符号是我定义的,其实模板渲染有个现成的工具: jinja2

下载jinja2: pip3 install jinja2

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="x-ua-compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1">
  7. <title>Title</title>
  8. </head>
  9. <body>
  10. <h1>姓名:{{name}}</h1>
  11. <h1>爱好:</h1>
  12. <ul>
  13. {% for hobby in hobby_list %}
  14. <li>{{hobby}}</li>
  15. {% endfor %}
  16. </ul>
  17. </body>
  18. </html>

index.html 文件

  1. from wsgiref.simple_server import make_server
  2. from jinja2 import Template
  3.  
  4. def index():
  5. with open("index2.html", "r") as f:
  6. data = f.read()
  7. template = Template(data) # 生成模板文件
  8. ret = template.render({"name": "Alex", "hobby_list": ["烫头", "泡吧"]}) # 把数据填充到模板里面
  9. return [bytes(ret, encoding="utf8"), ]
  10.  
  11. def home():
  12. with open("home.html", "rb") as f:
  13. data = f.read()
  14. return [data, ]
  15.  
  16. # 定义一个url和函数的对应关系
  17. URL_LIST = [
  18. ("/index/", index),
  19. ("/home/", home),
  20. ]
  21.  
  22. def run_server(environ, start_response):
  23. start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ]) # 设置HTTP响应的状态码和头信息
  24. url = environ['PATH_INFO'] # 取到用户输入的url
  25. func = None # 将要执行的函数
  26. for i in URL_LIST:
  27. if i[0] == url:
  28. func = i[1] # 去之前定义好的url列表里找url应该执行的函数
  29. break
  30. if func: # 如果能找到要执行的函数
  31. return func() # 返回函数的执行结果
  32. else:
  33. return [bytes("404没有该页面", encoding="utf8"), ]
  34.  
  35. if __name__ == '__main__':
  36. httpd = make_server('', 8000, run_server)
  37. print("Serving HTTP on port 8000...")
  38. httpd.serve_forever()

jinja2渲染示例

现在的数据是我们自己手写的,那可不可以从数据库中查询数据,来填充页面呢?

使用pymysql连接数据库:

  1. conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="xxx", db="xxx", charset="utf8")
  2. cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
  3. cursor.execute("select name, age, department_id from userinfo")
  4. user_list = cursor.fetchall()
  5. cursor.close()
  6. conn.close()

创建一个测试的user表:

  1. CREATE TABLE user(
  2. id int auto_increment PRIMARY KEY,
  3. name CHAR(10) NOT NULL,
  4. hobby CHAR(20) NOT NULL
  5. )engine=innodb DEFAULT charset=UTF8;

模板的原理就是字符串替换,我们只要在HTML页面中遵循jinja2的语法规则写上,其内部就会按照指定的语法进行相应的替换,从而达到动态的返回内容。

启动Django时报错

Django 启动时报错 “UnicodeEncodeError ...”

报这个错误通常是因为计算机名为中文,改成英文的计算机名重启下电脑就可以了。

Django 启动报错“SyntaxError: Generator expression must be parenthesized”

报这个错很大可能是因为使用了Python3.7.0,而目前(2018-06-12)Python3.7.0和Django还有点兼容性问题,换回Python3.6的环境即可。

开始使用Django写项目

如果前面实现原理的部分你没看懂,没关系,毕竟你距离架构师还有一段距离,现在不需要用到这么多的知识,但是接下来的内容是真正的Django基础

能看到这里相信你已经憋了很久了,还是先写个小项目轻松一下吧

用Django写Hello World

以下所有演示操作都是在终端下运行,当然有些部分也可以在Pycharm运行

  1. Django-admin startproject test_site # 创建Django测试工程
  2. cd test_site # 切换到当前工程路径
  3. python3 manage.py startapp test_app # 在该工程下创建一个测试项目
  4. tree # 按照树形列出工程下的文件和文件夹

结果如下

  1. .
  2. ├── manage.py
  3. ├── test_app
  4.    ├── __init__.py
  5.    ├── admin.py
  6.    ├── apps.py
  7.    ├── migrations
  8.       └── __init__.py
  9.    ├── models.py
  10.    ├── tests.py
  11.    └── views.py
  12. └── test_site
  13. ├── __init__.py
  14. ├── __pycache__
  15.    ├── __init__.cpython-36.pyc
  16.    └── settings.cpython-36.pyc
  17. ├── settings.py
  18. ├── urls.py
  19. └── wsgi.py

继续在终端执行命令

  1. python3 manage.py migrate
  2. python3 manage.py runserver

然后打开任意浏览器并输入 http://127.0.0.1:8000/

你可以看到Django开始工作了,接下来写Hello World,只需要修改其中的两个文件即可

在test_site -- test_site 下创建一个views.py 文件

  1. from django.shortcuts import HttpResponse
  2.  
  3. def hello(request):
  4. return HttpResponse("Hello world ! ")

修改urls.py 文件

  1. from django.conf.urls import url
  2. from django.contrib import admin
  3. from test_site import views
  4.  
  5. urlpatterns = [
  6. url(r'^admin/', admin.site.urls),
  7. url(r'^$', views.hello),
  8. ]

Python高级进阶(一)Python框架之Django入门的更多相关文章

  1. Python高级进阶(二)Python框架之Django写图书管理系统(LMS)

    正式写项目准备前的工作 Django是一个Web框架,我们使用它就是因为它能够把前后端解耦合而且能够与数据库建立ORM,这样,一个Python开发工程师只需要干自己开发的事情就可以了,而在使用之前就我 ...

  2. Python爬虫进阶之Scrapy框架安装配置

    Python爬虫进阶之Scrapy框架安装配置 初级的爬虫我们利用urllib和urllib2库以及正则表达式就可以完成了,不过还有更加强大的工具,爬虫框架Scrapy,这安装过程也是煞费苦心哪,在此 ...

  3. Python 高级网络操作 - Python Advanced Network Operations

    Python 高级网络操作 - Python Advanced Network Operations Half Open Socket, 一个单向的 socket 被称为 half open sock ...

  4. 【框架】Django入门学习笔记

    教程 Demo 教材2 教材3 [转] Django处理请求的工作机制 记住: 1.用manage.py runserver 启动Django服务器时就载入了在同一目录下的settings.py.该文 ...

  5. Python全栈开发-web框架之django

    一:web框架 什么是web框架? Web应用框架(Web application framework)是一种开发框架,用来支持动态网站.网络应用程序及网络服务的开发.这种框架有助于减轻网页开发时共通 ...

  6. 芝麻软件: Python爬虫进阶之爬虫框架概述

    综述 爬虫入门之后,我们有两条路可以走. 一个是继续深入学习,以及关于设计模式的一些知识,强化Python相关知识,自己动手造轮子,继续为自己的爬虫增加分布式,多线程等功能扩展.另一条路便是学习一些优 ...

  7. python 三大框架之一Django入门

    Django 是从真实世界的应用中成长起来的,它是由 堪萨斯(Kansas)州 Lawrence 城中的一个 网络开发小组编写的. 它诞生于 2003 年秋天,那时 Lawrence Journal- ...

  8. 芝麻HTTP:Python爬虫进阶之Scrapy框架安装配置

    初级的爬虫我们利用urllib和urllib2库以及正则表达式就可以完成了,不过还有更加强大的工具,爬虫框架Scrapy,这安装过程也是煞费苦心哪,在此整理如下. Windows 平台: 我的系统是 ...

  9. Python 高级进阶知识(一)

    参考 Python学习手册 第四版 1 from vs import import 模块 : 导入的一整个模块(python中模块对应一个py文件) 因为import使用一个变量名引用整个模块对象,所 ...

随机推荐

  1. Ubuntu16.04常用操作命令总结ing

    查看软件安装目录:whereis 软件名称(如:whereis mysql,where is sqlite3等) 安装软件:apt/apt-get install 软件名称(如:apt/apt-get ...

  2. ubuntu破解密码方法

    摘要: 开机按住任何键(shift)停住grub菜单,进入advanced option for ubuntu,出现的菜单中,光标移动至…(recovery mode)按E进入编辑,找到ro reco ...

  3. Python3简明教程(五)—— 流程控制之循环

    有些时候我们需要多次执行相同的任务,我们使用一个计数器来检查代码需要执行的次数.这个技术被称为循环. while循环 while语句的语法如下: while condition: statement1 ...

  4. UVA10129———欧拉道路

    题目 输入n(n≤100000)个单词,是否可以把所有这些单词排成一个序列,使得每个单词的第一个字母和上一个单词的最后一个字母相同(例如 acm,malform,mouse).每个单词最多包含1000 ...

  5. 油猴和EX-百度脚本 百度网盘下载

    pansoso.com 搜网盘 油猴和EX-百度脚本.zip https://aleikeji.pipipan.com/fs/845023-331102839

  6. Linux常用的操作指令

    1.pwd-显示当前所在位置 2.cd-进入当前目录 3.cd..-返回上一级目录 4..ls命令参数选项有很多,ls也是经常使用到的命令.如果不清楚命令的使用方式可以直接 ls --help来查看 ...

  7. Window服务程序(windows service application)如何调试

    服务程序不能通过常规的按F5或F11的方式来进行调试和运行,也无法立即运行一个服务或逐步调试它的代码. 因此,你必须安装并启动你的服务,然后附属(attach)一个Debugger到这个服务的进程上.

  8. Spring-01 注解实现IOC

    Spring框架四大原则 使用pojo进行轻量级和最小侵入式开发. 通过依赖注入和基于接口编程实现松耦合. 使用AOP和默认习惯进行声明式编程. 使用AOP和模板(template)减少模式化代码. ...

  9. OpenCV2:第四章 导出图像

    一.简介 一般我们用OpenCV来处理图像数据的时候,OpenCV已经把图像数据包装成一个图像数据类,我们只需要对类成员的像素值进行修改就行了. 但是在Windows开发的WinSDK/MFC中,对图 ...

  10. Vue通信、传值的多种方式,详解

    Vue通信.传值的多种方式,详解 转自:https://blog.csdn.net/qq_35430000/article/details/79291287 一.通过路由带参数进行传值 ①两个组件 A ...