Django框架简介

 web框架本质

咱们能够这样理解:全部的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。 这样咱们就能够本身实现Web框架了。html

import socket server = socket.socket() server.bind(('127.0.0.1',8080)) server.listen(5) while True: conn, addr = server.accept() data = conn.recv(1024) print(data)  # 将浏览器发来的消息打印出来
    conn.send(b"OK") conn.close()

能够说Web服务本质上都是在这十几行代码基础上扩展出来的。python

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

因此,必须有一个统一的规则,让你们发送消息、接收消息的时候有个格式依据,不能随便写。web

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

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

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

输出结果:django

""" 请求首行 b'GET / HTTP/1.1\r\n 请求头 Host: 127.0.0.1:8080\r\n Connection: keep-alive\r\n Cache-Control: max-age=0\r\n Upgrade-Insecure-Requests: 1\r\n User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36\r\n Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3\r\n Accept-Encoding: gzip, deflate, br\r\n Accept-Language: zh-CN,zh;q=0.9\r\n \r\n 请求体 ...... """

要想让咱们本身写的web server端正经起来,必需要让咱们的Web server在给客户端回复消息的时候按照HTTP协议的规则加上响应状态行,这样咱们就实现了一个正经的Web框架了flask

import socket server = socket.socket() server.bind(('127.0.0.1',8080)) server.listen(5) while True: conn, addr = server.accept() data = conn.recv(1024) #给回复的信息加上响应状态行
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n') conn.send(b'hello world') print(data)

咱们经过十几行代码简单地演示了web 框架的本质。后端

接下来就让咱们继续完善咱们的自定义web框架吧!

根据不一样的路径返回不一样的内容

这样就结束了吗? 如何让咱们的Web服务根据用户请求的URL不一样而返回不一样的内容呢?

咱们能够从请求相关数据里面拿到请求URL的路径,而后拿路径作一个判断...

import socket server = socket.socket() server.bind(('127.0.0.1',8080)) server.listen(5) while True: conn, addr = server.accept() data = conn.recv(1024) conn.send(b'HTTP/1.1 200 OK\r\n\r\n') data = data.decode('utf-8')  # 把从浏览器那里收到的字节类型的数据转换成字符串
    # print(data)
    target_url = data.split('\r\n')[0].split(' ')[1]  #按\r\n分割
    # 根据不一样的路径返回不一样内容
    if target_url == '/index': # conn.send(b'index')
        with open(r'D:\demo.html','rb') as f: conn.send(f.read()) elif target_url == '/login': conn.send(b'login') else: conn.send(b'404 error') conn.close()

基于wsgiref模块:

根据功能的不一样拆分红不一样的文件,用户在浏览器窗口输入url之因此可以获取到相应的资源,是由于后端早已经开设了相应的资源接口 

基于wsgiref模块以及文件拆分的特色:

若要开设新的资源
1.先在urls文件中写url与函数的对应关系
2.再去views文件中写对应的函数

urls.py:路由与视图函数的对应关系
views.py:里面就是放的一堆视图函数(视图函数能够是函数也能够是类)
templates文件夹:里面放的就是一堆html文件(模板文件夹)

动静态网页

静态网页:数据是写死的,万年不变

动态网页:数据是动态获取的,如获取当前时间,从数据库中取数据

jinja2模块 

提供了一个能够在html页面上书写相似于python后端的代码 来操做数据(模板语法) ,flask框架模板语法使用的就是jinja2模块,因此你只要下了flask框架 就会自动下载jinja2 

模板语法(jinja2模板语法很是贴近python语法 可是并非全部的框架使用的都是jinja模板语法)

{{ xxx }} <p>{{xxx.username}}</p>
<p>{{xxx['password']}}</p>
<p>{{xxx.get('hobby')}}</p>
<p>{{xxx.get('hobby')[0]}}</p>
<p>{{xxx.get('hobby').1}}</p>
View Code
{%for user_dict in xxx %} <tr>
        <td>{{ user_dict.id }}</td>
        <td>{{ user_dict.name }}</td>
        <td>{{ user_dict.hobby }}</td>
    </tr> {% endfor %}
View Code

基于wsgiref模块、jinjia2实现web框架

from views import * urls = [ ('/index',index), ('/login',login), ('/xxx',xxx), ('/get_time',get_time), ('/get_user',get_user), ('/get_info',get_info) ]
urls.py
def index(env): return 'index'

def login(env): return 'login'

def error(env): return '404 error'

def xxx(env): return 'xxx'

import time def get_time(env): # 该函数须要返回一个html页面
    current_time = time.strftime('%Y-%m-%d %X') # 文件操做 读取html文件
    with open(r'F:\python\templates\02 get_time.html','r',encoding='utf-8') as f: data = f.read()  # html文件内容 字符串
    data = data.replace('gfdgsffsda',current_time)  # 利用字符串的替换
    return data from jinja2 import Template def get_user(env): user_dict = {'username':'jason','password':123,'hobby':['read','study','run']} with open(r'F:\python\templates\04 get_info.html','r',encoding='utf-8') as f: data = f.read() temp = Template(data) res = temp.render(xxx=user_dict)  # 将user_dict传递给html页面 在页面上经过变量名xxx就可以获取到user_dict
    return res import pymysql def get_info(env): conn = pymysql.connect( host = '127.0.0.1', port = 3306, user = 'root', password = '123', database = 'day49', charset = 'utf8', autocommit = True ) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) sql = "select * from userinfo" cursor.execute(sql) data = cursor.fetchall()  # [{},{},{}]
    # 将列表套字典的结构数据 直接传递给html页面
    with open(r'D:get_info.html','r',encoding='utf-8') as f: res = f.read() # 利用jinja2模块
    tmp = Template(res) # 利用对象的render方法 将数据直接传递给html页面
    res = tmp.render(xxx=data) return res
views.py
from wsgiref.simple_server import make_server from views import *
from urls import urls def run(env,response): """ :param env: 请求相关的全部数据 :param response: 响应相关的全部数据 :return: 浏览器可以接受的内容 """ response('200 OK',[]) # print(env) # env是一个大字典 里面的PATH_INFO参数就是用户输入的后缀
    target_url = env.get('PATH_INFO') # if target_url == '/index':
    # # 一堆逻辑判断
    # return [b'index']
    # elif target_url == '/login':
    # return [b'login']
    # 先定义一个变量 用来存储可能匹配到的函数名
    func = None # 1 for循环获取一个个的url与函数对应关系的元组
    for url in urls:  # url = (),(),()
        # 2 判断当前用户访问的url与元组第一个元素是否一致
        if target_url == url[0]: # 3 若是相等 说明有对应的后端逻辑代码 将匹配到的函数名赋值给func
            func = url[1] # 4 一旦用户匹配上了响应的url 应该马上结束当前for循环了 由于再循环就没有意义
            break
    # 针对func是否有值 还须要判断
    if func: # 匹配上了 加括号直接调用
        res = func(env) else: # 匹配404逻辑代码
        res = error(env) return [res.encode('utf-8')]  # 返回函数的返回值


if __name__ == '__main__': # 监听127.0.0.1:8080 一旦有客户端来访问 会马上将make_server第三个参数加括号调用执行
    server = make_server('127.0.0.1',8080,run) server.serve_forever() # 启动服务端
wsgiref

web框架简介

python三大主流web框架

Django  优点:大而全,自身携带的组件和功能特别多,就相似于航空母舰。不足之处:笨重

Flask  优点:小而精,自身携带的组件和功能特别少,就相似于游骑兵,虽然自身功能比较少,可是第三方支持该框架的模块不少若是你将flask第三方模块所有叠加起来甚至能够超过django  不足之处:受限于第三方模块 

Tornado  异步非阻塞,自然支持高并发 甚至能够用它来开发游戏服务器

Django框架

Django框架注意事项:

  1. 计算机名称不能有中文 
  2. 项目文件名也不要用中文 
  3. 一个pycharm窗口就是一个单独的完整的项目 

Django版本:

推荐使用1.X版本里面的1.11.09~1.11.13

安装

pip3 install django==1.11.11

#测试是否安装成功
命令行输入 django-admin

建立django项目的两种方式

1.使用命令行建立

建立django项目:
django-admin startproject mysite(项目名)

效果:建立了一个mysite的文件夹

目录介绍
mysite/ ├── manage.py # 管理文件
└── mysite  # 项目目录
    ├── __init__.py ├── settings.py # 配置
    ├── urls.py  # 路由 --> URL和函数的对应关系
    └── wsgi.py  # runserver命令就使用wsgiref模块作简单的web server
启动Django项目:
python manage.py runserver  # django默认的端口号是8000

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

报这个错很大多是由于使用了Python3.7.0,而目前(2018-06-12)Python3.7.0和Django还有点兼容性问题。解决方案以下

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

报这个错误一般是由于计算机名为中文,改为英文的计算机名重启下电脑就能够了。

建立具备独立功能的app
python manage.py startapp app01  #一般状况下应该作到见名知意 

  app01
    -- migrations 文件夹
    -- __init__.py
    -- admin.py
    -- apps.py
    -- models.py
    -- tests.py
    -- views.py

app(application)的概念

django实际上是一个专一于开发app的web框架,一个空的django项目就相似因而一所大学,app就相似于大学里面的各个学院。

每一个app其实就相似于不一样的功能模块

  购物网站
    用户相关 user
      用户相关的app
    订单相关 order
      订单相关的app
    投诉相关 tousu
      投诉相关的app

不一样的功能模块推荐使用不一样的app去开发,django支持多app

Django主要文件功能
 mysite -mysite --__init__.py --settings.py 项目配置文件 --urls.py 路由视图函数对应关系 项目的总路由 --wsgi.py -manage.py
app01
--migrations文件夹 数据库改动记录 --__init__.py --__init__.py --admin.py django后台管理 --apps.py 注册app相关 --models.py 模型类(ORM) --tests.py 测试文件 --views.py 视图函数(******)


     db.sqlite3 django自带的一个小型用于本地测试的数据库(对日期格式的数据不是很敏感)

2.使用pycharm建立

注意:1.使用命令行建立的django项目是不会自动建立templates模板文件夹,只能本身手动建立

2.命令行建立的django项目不但没有templates文件夹,配置文件中也没有填写路径,而pycharm建立的会自动添加


 容易犯的错误:代码修改了始终没有效果

1.在同一个端口起了多个服务 一直跑的是最开始的那个服务
2.浏览器缓存问题


解决浏览器缓存以下图

 

 补充:简化命令的方式

项目配置文件夹注意事项:(注册)

注意:建立app以后必定必定要先去setting文件中注册

 

pycharm建立的Django项目的配置文件

命令行建立的Django项目的配置文件

 

Django可以自动重启,可是它的重启机制只要检测到你的代码有变化,则在必定的时间间隔内就会自动重启。因此有时候可能会出现 你代码还没写完就已经自动重启了

Django基础必备三件套

HttpResponse:返回字符串

render:返回html页面 并能够给html页面传数据

    模板的渲染(将数据在后端按照模板语法放入html对应的位置)

redirect:重定向

from django.shortcuts import render,HttpResponse,redirect # Create your views here.
def index(request): return HttpResponse('字符串') def login(request): return render(request,'templates文件夹下的html文件名',{'user_dict':{'username':'jason','password':123},'userxxx':'hello world'})) def home(request): # return redirect('http://www.baidu.com')
    return redirect('/index')
相关文章
相关标签/搜索