加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

Django 14天从小白到进阶- Day1 Django 初识

发布时间:2020-12-17 00:07:32 所属栏目:Python 来源:网络整理
导读:本节内容 p class="li1" span class="s1"span class="s2"Http原理介绍 p class="li1" span class="s3"span class="s2"自行开发一个Web框架 p class="li1" span class="s3"span class="s2"WSGI介绍 p class="li1" span class="s3"span class="s2"Django介绍 p

本节内容

<p class="li1"><span class="s1"><span class="s2">Http原理介绍


<p class="li1"><span class="s3"><span class="s2">自行开发一个Web框架


<p class="li1"><span class="s3"><span class="s2">WSGI介绍


<p class="li1"><span class="s3"><span class="s2">Django介绍


<p class="li1"><span class="s3"><span class="s2">MVC/MTV


<p class="li1"><span class="s3"><span class="s2">Django安装


<p class="li1"><span class="s3"><span class="s2">创建项目与APP


<p class="li1"><span class="s3"><span class="s2">开发第一个页面

为什么学Django?

Good question,知Python者必知Django,因为这可是Python语言里最流行&强大的Web框架,同时亦是全球第5大WEB框架,可快速构建稳定强大的WEB项目,大大提高开发效率,很多知名项目都是基于Django开发,如Disqus、Pinterest、Instagram、Bitbucket等, Django官方Slogan是The framework for perfectionist with deadline! 一个为完美主义者且又开发工期很紧的人设计的框架,事实确实如此,Django自身集成了丰富的WEB开发通用组件,如用户认证、分页、中间件、缓存、session等,可以避免浪费大量时间重复造轮子。

ttp原理介绍

这个Client和Server端本质上是一个Socket客户端和服务器端,Http协议可以说是基于Socket的再上层封装。

HTTP特性

基于TCP/IP协议

你每次打开百度或其它网站,都需要先建立好TCP/IP会话,当然这个浏览器会帮你做了。

短连接

你打开?https://www.luffycity.com/? 或其它网站, 当服务器端把这个页面的内容全返回后,就把这次连接断开了,会话就结束了,你在浏览器上看到页面内容已经是下载到本地的了,所以此时如果服务器端更新了内容,你本地的页面自然是不会跟着变的。除非你再刷新一下,这样就又进行了一次会话。那为何是短连接呢?你想一想

被动响应

这个很好理解,你不请求百度,百度是不会主动连接你的。

无状态

无状态是指,当浏览器发送请求给服务器的时候,服务器响应,但是同一个浏览器再发送请求给服务器的时候,他会响应,但是他不知道你就是刚才那个浏览器,简单地说,就是服务器不会去记得你,所以是无状态协议。

自行开发一个Web Server

既然Http协议本质上是基于Socket做的,我们又学过Socket了,那能不能自己开发一个Web Server呢? 回答是of course.?

<div class="cnblogs_Highlighter">
<pre class="brush:python;gutter:true;"># -- coding:utf-8 --

created by Alex Li - 路飞学城

import socket

def main():
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sock.bind(('localhost',8000))
sock.listen(5)

while True:
    # 等待浏览器访问
    conn,addr = sock.accept()
    # 接收浏览器发送来的请求内容
    data = conn.recv(1024)
    print(data)

    # 给浏览器返回内容
    conn.send(b"HTTP/1.1 200 OKrnContent-Type:text/html; charset=utf-8rnrn")
    conn.send("电脑前的你长的真好看!".encode("utf-8"))

    # 关闭和浏览器创建的socket连接
    conn.close()

if name == "main":
main()

  

我靠,这么简单,是的,就这么简单,但你现在只是返回了一句话,如果是要返回一个图片呢?一个文件呢?这就涉及你自己要负责实现文件的传送了,我们学socket传文件时,遇到过粘包问题,解决起来挺麻烦的,你现在要自己通过Socket把Http协议里的各种功能都实现了的话,估计孩子都长大了。与其浪费时间自己写,不如直接用先人的。

WSGI介绍

Python的wsgiref是基于WSGI规范封装的模块,我们可以在这个模块基础上开发我们的web server?

基于WSGI开发一个WEB服务器

from wsgiref.simple_server import make_server

def run_server(environ,start_response):
"""
当有用户在浏览器上访问:http://127.0.0.1:8000/,立即执行该函数并将函数的返回值返回给用户浏览器
:param environ: 请求相关内容,比如浏览器类型、版本、来源地址、url等
:param start_response: 响应相关
:return:
"""

start_response('200 OK',[('Content-Type','text/html;charset=utf-8')])
return [bytes('<h1>我旁边的这个人长的真丑呀!!',encoding='utf-8'),]

if name == 'main':
httpd = make_server('localhost',8001,run_server)
httpd.serve_forever()

别人家的网站和我们的网站  

<p class="p1"><span class="s1">你看别人的网站,可以根据URL不同看到不同的内容,比如这个:<a href="http://jandan.net/ooxx"&gt;<span class="s2">煎蛋网<span class="Apple-converted-space">?

<p class="p1"><span class="s1">但我们刚才自己开发的网站,永远只能看到同样的内容。


<p class="p1">?


<p class="p1"><span class="s1">怎么办?我们自己也可以处理url呀


<div class="cnblogs_code" onclick="cnblogs_code_show('a67136a7-fc90-43e5-a178-6eabff81c7bb')">
<img id="code_img_closed_a67136a7-fc90-43e5-a178-6eabff81c7bb" class="code_img_closed" src="https://www.52php.cn/res/2019/02-10/23/1c53668bcee393edac0d7b3b3daff1ae.gif" alt=""><img id="code_img_opened_a67136a7-fc90-43e5-a178-6eabff81c7bb" class="code_img_opened" style="display: none;" onclick="cnblogs_code_hide('a67136a7-fc90-43e5-a178-6eabff81c7bb',event)" src="https://www.52php.cn/res/2019/02-10/23/405b18b4b6584ae338e0f6ecaf736533.gif" alt=""><div id="cnblogs_code_open_a67136a7-fc90-43e5-a178-6eabff81c7bb" class="cnblogs_code_hide">

 
 
 
  wsgiref.simple_server  
 
       
 
       
 
 
      
     urlpatterns =         (         (  
      
 
      
         
     start_response(,[(,     url = environ.get(     urlpatterns = 
     func = 
      item           item[0] ==             func = item[1             
               [bytes(func(),encoding=               [bytes(,]
 
   ==      httpd = make_server(,8001     httpd.serve_forever()

真棒,轻松的就可以使你的web server支持多页面了。但你高兴不起来,因为你看到人家别人的网站多姿多彩,各种图片、各种动效,你的网站只能显示文字。感觉像是上个世纪的产物,不刺激,哈,那就来点刺激的,让你的网站也支持一下图片和样式。

<span style="color: #0000ff;">from wsgiref.simple_server <span style="color: #0000ff;">import<span style="color: #000000;"> make_server
<span style="color: #0000ff;">import<span style="color: #000000;"> re,os
BASE_DIR = os.path.dirname(os.path.abspath(<span style="color: #800080;">file<span style="color: #000000;">))

<span style="color: #0000ff;">def<span style="color: #000000;"> img_handler(url):
img_relative_path = re.sub(<span style="color: #800000;">"<span style="color: #800000;">/static/<span style="color: #800000;">",<span style="color: #800000;">"<span style="color: #800000;">imgs/<span style="color: #800000;">",url,count=1<span style="color: #000000;">)
img_path =<span style="color: #000000;"> os.path.join(BASE_DIR,img_relative_path)
<span style="color: #0000ff;">print(<span style="color: #800000;">'<span style="color: #800000;">img<span style="color: #800000;">'<span style="color: #000000;">,BASE_DIR,img_path)
f = open(img_path,<span style="color: #800000;">'<span style="color: #800000;">rb<span style="color: #800000;">'<span style="color: #000000;">)
data =<span style="color: #000000;"> f.read()
f.close()
<span style="color: #0000ff;">return<span style="color: #000000;"> data

<span style="color: #0000ff;">def<span style="color: #000000;"> western():
data = <span style="color: #800000;">'''<span style="color: #800000;">

欢迎来到欧美专区

<img src='/static/test_america.jpg' width='800px'/>

</span><span style="color: #800000;"&gt;'''</span>

<span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; data

<span style="color: #0000ff;">def<span style="color: #000000;"> japan():
data = <span style="color: #800000;">'''<span style="color: #800000;">

欢迎来到日本人专区

<img src='/static/testimg.gif' />

</span><span style="color: #800000;"&gt;'''</span>

<span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; data

<span style="color: #0000ff;">def<span style="color: #000000;"> routers():
<span style="color: #800000;">"""<span style="color: #800000;">负责把url与对应的方法关联起来<span style="color: #800000;">"""<span style="color: #000000;">
urlpatterns =<span style="color: #000000;"> (
(<span style="color: #800000;">'<span style="color: #800000;">/western/<span style="color: #800000;">'<span style="color: #000000;">,(<span style="color: #800000;">'<span style="color: #800000;">/japan/<span style="color: #800000;">'<span style="color: #000000;">,)

</span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; urlpatterns

<span style="color: #0000ff;">def<span style="color: #000000;"> run_server(environ,start_response):
<span style="color: #800000;">"""<span style="color: #800000;">
当有用户在浏览器上访问:http://127.0.0.1:8000/,立即执行该函数并将函数的返回值返回给用户浏览器
:param environ: 请求相关内容,比如浏览器类型、版本、来源地址、url等
:param start_response: 响应相关
:return:
<span style="color: #800000;">"""<span style="color: #000000;">
content_type = <span style="color: #800000;">'<span style="color: #800000;">text/html;charset=utf-8<span style="color: #800000;">'<span style="color: #000000;">

url </span>= environ.get(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;PATH_INFO</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;)
urlpatterns </span>=<span style="color: #000000;"&gt; routers()

func </span>=<span style="color: #000000;"&gt; None
</span><span style="color: #0000ff;"&gt;if</span> url.startswith(<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;/static/</span><span style="color: #800000;"&gt;'</span>): <span style="color: #008000;"&gt;#</span><span style="color: #008000;"&gt;代表是张图片</span>
    content_type = <span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;text/jpg;charset=utf-8</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;
    start_response(</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;200 OK</span><span style="color: #800000;"&gt;'</span>,[(<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;Content-Type</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;,content_type)])

    img_data </span>=<span style="color: #000000;"&gt; img_handler(url)
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; [img_data,]

</span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt;:
    </span><span style="color: #0000ff;"&gt;for</span> item <span style="color: #0000ff;"&gt;in</span><span style="color: #000000;"&gt; urlpatterns:
        </span><span style="color: #0000ff;"&gt;if</span> item[0] ==<span style="color: #000000;"&gt; url:
            func </span>= item[1<span style="color: #000000;"&gt;]
            </span><span style="color: #0000ff;"&gt;break</span><span style="color: #000000;"&gt;

start_response(</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;200 OK</span><span style="color: #800000;"&gt;'</span>,content_type)])
</span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; func:
    </span><span style="color: #0000ff;"&gt;return</span> [bytes(func(),]
</span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt;:
    </span><span style="color: #0000ff;"&gt;return</span> [bytes(<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;404 not found.</span><span style="color: #800000;"&gt;'</span>,]

<span style="color: #0000ff;">if <span style="color: #800080;">name == <span style="color: #800000;">'<span style="color: #800000;">main<span style="color: #800000;">'<span style="color: #000000;">:
httpd = make_server(<span style="color: #800000;">'<span style="color: #800000;">localhost<span style="color: #800000;">',run_server)
httpd.serve_forever()

执行一下看看。?

真是技术改变生活呀!

能显示图片只是冰山一角,我们需要继续开发一下功能:

  • 用户表单提交,即:用户向后台发送表单数据
  • 数据库操作
  • 加载样式和JS文件
  • 允许用户下载文件

虽然自己开发有乐趣,但确实比较麻烦,在项目开发中,追求的更多是效率,而不是乐趣,所以还是尽量不要重复造轮子啦,我们接下来要学的Django框架就是帮我们已经造好的轮子。

Web框架的本质

虽然自己写Web Server比较麻烦,但是我们从中也了解web框架的本质:

  1. 浏览器是socket客户端,网站是socket服务端
  2. wsgi,是一个规范,wsgiref实现了这个规范并在其内部实现了socket服务端
  3. 根据 url 的不同执行不同函数,即:路由系统
  4. 函数,即:视图函数
  5. 图片、css、js文件 统一称为静态文件,需要读取内容直接返回给用户浏览器

Django来了

安装

* 注意,2.0 跟1.x版本上用法上是有些区别的,本课程我们主讲2.x。?

安装成功后,就会出现??命令

创建Project

你想做个网站,首先我们要创建一个django project,以后的代码都放在这个项目里。

创建好的项目目录结构

命令帮助我们创建了几个文件,通过文件将功能代码归类。  </pre>

创建APP

一个项目中会包含一个或多个子项目,每个项目实现不同的功能和服务,如微信里包含基本通信功能,还有支付、小程序等,每块业务都可以分为一个子项目。在django中, 我们管这个子项目叫app。下面是一个有多app的项目

为了开发和维护方便,每个子项目(app)都会有一个独立文件夹来存放各自的业务代码。一般程序简单情况下,只需要创建一个app即可。

Django的第一次请求  

HTTP请求本质

上面的一次django请求都经历了哪些过程呢?我们来剖析下

浏览器访问网站的本质:socket客户端、socket服务端之间的收发消息。

流程:

1. 【服务端】网站启动,并监听IP和端口,如:127.0.0.1:80,等待客户端来连接…?2. 【客户端】浏览器中输入http://www.oldboyedu.com/index/,浏览器先后进行:

  1.   连接:域名解析得到网站IP,并根据端口进行连接。
  2.   发送消息:将请求数据发送给服务端,发送数据本质上是字符串,格式如下:

3. 【服务端】接收用户请求发来的数据,并根据请求字符串解析,并做出响应。  

4. 【客户端】接收服务端响应的内容,将响应体展示在浏览器上,响应头偷偷保存到浏览器。

5.?【客户端】【服务端】连接断开,Http请求终止(体现了Http短连接)。  

注意:请求和响应基本包含请求头和请求体并通过rnrn进行分割。

用Django 开发用户登录页面

用户登录是个表单啦,但目前我们只会用Django返回字符串,表单涉及的html元素比较多,总不能在view.py里写好返回吧?这太low了,是的,怎么可以不low? 是时候表演真正的技术啦。

Django有个叫模板(Template)的东东,可以直接把你的Html代码写在模板里,返回给浏览器。

模板初探

想用模板仅需2步,

  1. 配置存html文件的模板目录
  2. 在你的views.py的响应函数里返回对应的html文件?

是时候该讲讲套路啦?

刚才在开发用户登录页面时,我们的请求处理流程是这样的, 请求-> url.py -> views.py -> template -> 浏览器, 流程为什么这样安排?中间如何要从数据库里拿数据,是应该在哪个阶段?其实Django或其它web语言的web框架在开发时都符合了某种神秘的套路,这个套路是什么?即MVC.

MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式

不懂对不对?其实说白了,就是把Web开发中一个请求处理流程分成了3部分,每部分专注做自己的事。

  1. Model(模型)一般对应数据库操作、纪录的存取
  2. View(视图)决定着如何展示数据
  3. Controller(控制器)负现处理用户交互的部分。控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

MVC & MTV?

Django是一个MTV框架,其架构模板看上去与传统的MVC架构并没有太大的区别。Django将MVC中的视图进一步分解为 Django视图 和 Django模板两个部分,分别决定 “展现哪些数据” 和 “如何展现”,使得Django的模板可以根据需要随时替换,而不仅仅限制于内置的模板。至于MVC控制器部分,由Django框架的URLconf来实现。

再具体点的图

从下一章开始 ,我们会一点点把model,views,template,url 每个都延伸开来讲。?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读