Fork me on GitHub

Django学习笔记1

Web框架本质

所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。 这样我们就可以自己实现Web框架了。我们定义一个socket server端程序,与浏览器(client端)进行互交试试

import socket

sk = socket.socket()
sk.bind(("127.0.0.1", 8001))
sk.listen()


while True:
    conn, addr = sk.accept()
    data = conn.recv(8096)
    print(data)  # 将浏览器发来的消息打印出来
    conn.send(b"OK")
    conn.close()

b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8001\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'

服务端收到了http的请求头,如此就可以和客户端进行互交了。所以可以说Web服务本质上都是在这十几行代码基础上扩展出来的,只要请求和响应满足一定的规范(http协议),就可以实现我们写的server端和client端进行互交了。

HTTP协议详解:https://www.cnblogs.com/wlx97e6/p/9550171.html

HTTP GET请求的格式:

HTTP响应的格式:

定义自己的简易web框架

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', 8000))
sock.listen()

while True:
    conn, addr = sock.accept()
    data = conn.recv(8096)
    # 给回复的消息加上响应状态行
    conn.send(b"HTTP/1.1 200 OK\r\n\r\n")  # 包括响应行和响应头和换行
    conn.send(b"OK")  # 回复响应正文
    conn.close()

此时在访问127.0.0.1:8000即可得到OK界面

根据不同的路径返回不同的内容

如何让我们的Web服务根据用户请求的URL不同而返回不同的内容呢?

"""
根据URL中不同的路径返回不同的内容,返回独立的HTML页面
"""

import socket
sk = socket.socket()
sk.bind(("127.0.0.1", 8080))  # 绑定IP和端口
sk.listen()  # 监听


# 将返回不同的内容部分封装成函数
def index(request):
    # 读取index.html页面的内容
    with open("index.html", "r", encoding="utf8") as f:
        s = f.read()
    # 返回字节数据
    return bytes(s, encoding="utf8")


def home(request):
    with open("home.html", "r", encoding="utf8") as f:
        s = f.read()
    return bytes(s, encoding="utf8")


# 定义一个url和实际要执行的函数的对应关系
list1 = [
    ("/index/", index),
    ("/home/", home),
]

while 1:
    # 等待连接
    conn, add = sk.accept()
    data = conn.recv(8096)  # 接收客户端发来的消息
    # 从data中取到路径
    data = str(data, encoding="utf8")  # 把收到的字节类型的数据转换成字符串
    # 按\r\n分割
    data1 = data.split("\r\n")[0]
    url = data1.split()[1]  # url是我们从浏览器发过来的消息中分离出的访问路径
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')  # 因为要遵循HTTP协议,所以回复的消息也要加状态行
    # 根据不同的路径返回不同内容
    func = None  # 定义一个保存将要执行的函数名的变量
    for i in list1:
        if i[0] == url:
            func = i[1]
            break
    if func:
        response = func(url)
    else:
        response = b"404 not found!"

    # 返回具体的响应消息
    conn.send(response)
    conn.close()

这样即可实现根据不同的url返回不同的界面

让网页动态起来

这网页能够显示出来了,但是都是静态的啊。页面的内容都不会变化的,我想要的是动态网站。

没问题,我也有办法解决。我选择使用字符串替换来实现这个需求。(这里使用时间戳来模拟动态的数据)

"""
根据URL中不同的路径返回不同的内容--函数进阶版
返回HTML页面
让网页动态起来
"""

import socket
import time

sk = socket.socket()
sk.bind(("127.0.0.1", 8080))  # 绑定IP和端口
sk.listen()  # 监听


# 将返回不同的内容部分封装成函数
def index(request):
    with open("index.html", "r", encoding="utf8") as f:
        s = f.read()
        now = str(time.time())
        s = s.replace("@@oo@@", now)  # 在网页中定义好特殊符号,用动态的数据去替换提前定义好的特殊符号
    return bytes(s, encoding="utf8")


def home(request):
    with open("home.html", "r", encoding="utf8") as f:
        s = f.read()
    return bytes(s, encoding="utf8")


# 定义一个url和实际要执行的函数的对应关系
list1 = [
    ("/index/", index),
    ("/home/", home),
]

while 1:
    # 等待连接
    conn, add = sk.accept()
    data = conn.recv(8096)  # 接收客户端发来的消息
    # 从data中取到路径
    data = str(data, encoding="utf8")  # 把收到的字节类型的数据转换成字符串
    # 按\r\n分割
    data1 = data.split("\r\n")[0]
    url = data1.split()[1]  # url是我们从浏览器发过来的消息中分离出的访问路径
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')  # 因为要遵循HTTP协议,所以回复的消息也要加状态行
    # 根据不同的路径返回不同内容
    func = None  # 定义一个保存将要执行的函数名的变量
    for i in list1:
        if i[0] == url:
            func = i[1]
            break
    if func:
        response = func(url)
    else:
        response = b"404 not found!"

    # 返回具体的响应消息
    conn.send(response)
    conn.close()

本质到这已经讲完了,下面讲框架的基础

服务器程序和应用程序

对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。

服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。

应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。

 

这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。

这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

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

常用的WSGI服务器有uwsgi(性能比wsgiref好)、Gunicorn。而Python标准库提供的独立WSGI服务器叫wsgiref(本质是socket服务器),Django开发环境用的就是这个模块来做服务器,Werkuzeug也是实现了wsgi的模块(flask使用),下面wsgi左右的都是服务器,不过各自的功能不同,具体功能看下面的abc

 

 

web框架本质和Python中 Web框架的分类

web框架的本质:
socket服务端 与 浏览器的通信

socket服务端功能划分:
a. 负责与浏览器收发消息(socket通信) --> wsgiref/uWsgi/gunicorn...
b. 根据用户访问不同的路径执行不同的函数
c. 从HTML读取出内容,并且完成字符串的替换 --> jinja2(模板语言)

Python中 Web框架的分类:

按上面三个功能划分:

1. 框架自带a,b,c --> Tornado
2. 框架自带b和c,使用第三方的a --> Django  第三方的a是wsgiref
3. 框架自带b,使用第三方的a和c --> Flask  第三方的a是Werkzeug,c是jinja2

按另一个维度来划分:

1. Django --> 大而全(你做一个网站能用到的它都有)
2. 其他 --> Flask 轻量级

Django框架简介

MVC框架和MTV框架

MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller),具有耦合性低、重用性高、生命周期成本低等优点。

Django框架的设计模式借鉴了MVC框架的思想,也是分成三部分,来降低各个部分之间的耦合性。

Django框架的不同之处在于它拆分的三部分为:Model(模型)、Template(模板)和View(视图),也就是MTV框架。

Django的MTV模式

       Model(模型):负责业务对象与数据库的对象(ORM)

       Template(模版):负责如何把页面展示给用户

       View(视图):负责业务逻辑,并在适当的时候调用Model和Template

此外,Django还有一个urls分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

Django框架图示

完整的简易请求流程

0. 启动服务端,等待客户端(用户的浏览器)来连接
1. 在浏览器地址栏输入URL,与服务端建立连接,浏览器发送请求
2. 服务端收到请求消息,解析请求消息,根据路径和函数的对应关系,找到将要执行的函数
3. 执行函数,打开HTML文件,进行字符串替换,得到一个最终要返回的HTML内容
4. 按照HTTP协议的消息格式要求,把HTML内容回复给用户浏览器(发送响应)
5. 浏览器收到响应的消息之后,按照HTML的规则渲染页面.
6. 关闭连接

Django的安装和启动

安装(安装最新LTS版)

LTS为官方长期维护的版本:

 

这里有1.11版本的官方翻译文档,我看的时候官方翻译的文档没有1.11版本的,只有2.0及以后的,若看2.0以后,直接去官方看即可

1.11的中文文档  还有 2.0的官方文档

运行下面指令安装完成即可使用django-admin命令查看

pip3 install django==1.11.11

执行完成会在当前目录下安装django

创建一个django项目

(一)命令行创建方式(不推荐使用)

     1. cd到你要保存Django项目的目录
     2. Django-admin startproject 项目名   --> 会在当前目录创建Django项目

django-admin startproject mysite
# 若Django未加入到环境变量,可以到目录下找django文件 H:\python\venvs\Mydjango\Scripts\django-admin startproject newdjango

(二)pycharm中创建django项目

  1.首先你要有一个安装了django的python解释器(没有的话pycharm一般也会帮忙创建,自动调用pip命令安装django,个别版本会有问题)

    1.如果是安装的纯净的解释器(官网直接下的):cd到解释器安装目录下Script目录的位置(里面有pip.exe的那个),然后执行pip3 install django==1.11.11,这时你就有一个安装了django的python解释器

    2.如果是pycharm中创建的虚拟环境,直接在虚拟环境的带有python.exe的同级目录下执行pip3 install django==1.11.11

    3.如果是别的虚拟环境。。。。。我也不会

  2.然后点击新建项目(选择安装了django的python解释器

然后就可以了,测试是否创建成功就在项目里执行一下,然后点击控制台的链接,然后就可以看到祝贺界面

也可以在命令行界面启动,保证自己保持和manage.py在同一目录下,然后执行 

python manage.py runserver

你应该会看到如下输出:

Performing system checks...

System check identified no issues (0 silenced).

You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.

十月 23, 2018 - 15:50:53
Django version 2.1, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

然后点击控制台的链接,然后就可以看到祝贺界面

启动Django报错:

Django启动:

Django项目在pycharm中启动时,不要运行单个文件,要点击绿色三角运行

命令行启动

在项目的根目录下(也就是有manage.py的那个目录),运行:

python3 manage.py runserver IP:端口--> 在指定的IP和端口启动
python3 manage.py runserver 端口 --> 在指定的端口启动
python3 manage.py runserver --> 默认在本机的8000端口启动

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

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

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

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

刚开始学习时可在配置文件中暂时禁用csrf中间件,方便表单提交测试。

目录简单介绍

1、外层总目录介绍

在执行完    django-admin startproject mysite   的创建

mysite/  # 项目根目录
├── manage.py  # 管理文件,互交命令行工具
└── mysite  # 项目目录(纯Python包)
    ├── __init__.py  # Python包必带
    ├── settings.py  # 配置
    ├── urls.py  # 路由 --> URL和函数(类)的对应关系
    └── wsgi.py  # runserver命令就使用wsgiref模块做简单的web server

这些文件是:

  • 外层的mysite/根目录仅仅是项目的一个容器。 它的名字与Django无关;可以将其重命名为你喜欢的任何内容。
  • manage.py:一个命令行工具,可以使你用多种方式对Django项目进行交互。 你可以在django-admin和manage.py中读到关于manage.py的所有细节。
  • 内层的mysite/目录是你的项目的真正的Python包。 它是你导入任何东西时将需要使用的Python包的名字(例如 mysite.urls)。
  • mysite/__init__.py:一个空文件,它告诉Python这个目录应该被看做一个Python包。 如果你是Python初学者,请在官方Python文档中阅读关于python包的更多内容
  • mysite/settings.py:该Django 项目的设置/配置。 Django settings 将告诉你这些设置如何工作。
  • mysite/urls.py:此Django项目的URL声明;Django驱动的网站的“目录”。 你可以在URL dispatcher 中阅读到更多关于URL的内容。
  • mysite/wsgi.py:用于你的项目的与WSGI兼容的Web服务器入口。 更多细节请参见如何使用WSGI部署

 2、APP层目录介绍

应用和项目的区别:

项目和应用之间有什么不同? 应用是一个Web应用程序,它完成具体的事项 —— 比如一个博客系统、一个存储公共档案的数据库或者一个简单的投票应用。 一个项目是特定网站的配置和应用程序的集合。 一个项目可以包含多个应用。 一个应用可以运用到多个项目中去。

要创建你的应用,请确保与manage.py在同一目录中,并键入以下命令:

python manage.py startapp polls

  这将创建一个目录polls,它的结构如下:

polls/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

       1、migrations目录:此目录记录了数据库变化情况

       2、admin.py文件: Django 为我们提供的后台管理

       3、apps.py文件:配置当前app

       4、models.py文件:此文件用来定义数据库表,ORM,写指定的类,通过命令可以创建数据库结构

       5、tests.py文件:此文件用于单元测试

       6、urls.py文件:此文件是APP自己的路由规则所在的文件(上面目录没有,是二级路由时用,可手动创建)

       7、views.py文件:此文件是视图函数的代码所在文件,关于视图函数会在后面的博客中详细介绍

 3、静态文件目录

创建工程完成后,我们需要在工程根目录下创建一个“static”目录用户保存静态文件。

关于静态文件,在网站中,那些图片、css、js等一般情况下内容不会变化的文件都是静态文件,我们可以把这些文件都放这个静态文件目录中。

静态目录创建完成后需要在settings.py文件中添加如下的配置:

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,'static'),
)

4、模板文件目录

  模板文件就是指那些html文件,在用户访问的过程中,Django会将页面上的数据套用到模板文件,渲染成一个完整的字符串然后返回给客户端,这些模板文件存放在templates目录中,关于模板文件以及模板语言的语法将会在后续的博客中详细介绍。

 

总目录https://www.cnblogs.com/wlx97e6/p/9143284.html

posted @ 2018-08-30 22:10  醉生卐梦死  阅读(416)  评论(0编辑  收藏  举报