11 Jun 18 Django

11 Jun 18

一、今日面试题(python全栈课前练习题)

------------------------------------------------

s = "Alex SB 哈哈 x:1 y:2 z:3 自行车"

 

# 问题1:如何取到["Alex SB 哈哈 x:1 y:2 z:3", "自行车"]?

ret1 = s.split(" ")

print(ret1)

 

# 问题2:如何在上面结果基础上拿到["Alex", "SB", "哈哈"]?

ret2 = ret1[0].split(" ")[0].split(" ")

print(ret2)

 

# 问题3:如何在上面结果基础上拿到"SB"?

ret3 = ret2[1]

print(ret3)

 

----------------------------------------------

有一个列表,他的内部是一些元祖,元祖的第一个元素是姓名,第二个元素是爱好。现在我给你一个姓名,如"Egon",如果有这个姓名,就打印出他的爱好,没有就打印查无此人。

list1 = [

    ("Alex", "烫头"),

    ("Egon", "街舞"),

    ("Yuan", "喝茶")

]

 

for i in list1:

    if "Egon" == i[0]:

        print(i[1])

        break

else:

    print("查无此人")

 

-----------------------------------------

有一个HTML文件"login.html"

 

# 问题1:我如何读取它的文本内容保存到变量html_s?

with open("login.html", "r", encoding="utf8") as f:

    html_s = f.read()

print(html_s)

 

# 问题2:我如何读取它的二进制内容保存到变量html_b?

with open("login.html", "rb") as f:

    html_b = f.read()

print(html_b)

 

---------------------------------------------

s2 = "Alex 花了一百万买了辆电动车,真@@xx@@。"

 

# 问题1:如何把上面的s2转变成"Alex 花了一百万买了辆电动车,真SB。"

 

ret4 = s2.replace("@@xx@@", "SB")

print(ret4)

 

---------------------------------------------

字节和字符串的相互转换

s = "o98k"

ret = bytes(s, encoding="utf8")

print(ret)

 

b = b'hello world!'

ret2 = str(b, encoding="utf8")

print(ret2)

 

---------------------------------------------

HTTP协议:规定了浏览器和服务器之前发送信息的格式

请求(request):浏览器往服务端发送的消息

响应(response):服务端回复给浏览器的消息

 

二、今日内容

1、web框架本质

网址->IP地址和端口->找到网站服务器->把HTML文件发回给浏览器->按照HTML格式渲染成最终网页

https://www.cnblogs.com/liwenzhou/p/8258992.html

半成品自定义web框架->加上http协议规则的web框架-> 根据不同的路径返回不同的内容(若干if判断)->根据不同的路径返回不同的内容(函数版,定义一个url和实际要执行的函数的对应关系)->返回具体的HTML文件->返回动态的HTML文件

 

返回动态的HTML文件

"""

根据浏览器访问的路径的不同,返回不同的内容

将不同页面的处理代码封装到函数中

优化频繁的if判断

返回具体的HTML文件

实现不同的用户得到不同的HTML页面

"""

import socket

import time

 

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.bind(('127.0.0.1', 8888))

server.listen()

 

def home(url):

    s = "this is {} page!".format(url)

    return bytes(s, encoding="utf8")

 

def index(url):

    return b'<h1>index page</h1>'. # 浏览器根据html标签,自动渲染

 

def user(url):

    # 不同的用户得到的页面上显示不同的时间

    c_time = str(time.time())

    with open("user.html", "r") as f:

        data_s = f.read()

        data_s = data_s.replace("@@xx@@", c_time)  # 替换后的字符串数据

        return bytes(data_s, encoding="utf8")

 

def login(url):

    with open("login.html", "rb") as f:

        return f.read()

 

# url和将要执行的函数的对应关系

url2func = [

    ("/index", index),

    ("/home", home),

    ("/user", user),

    ("/login", login),

]

 

while 1:

    conn, addr = server.accept()

    data = conn.recv(8096)  # 收消息

    # print(data)

    # 从浏览器发送消息中,拿到用户访问的路径

    data_str = str(data, encoding="utf8")

    # print(data_str)

    url = data_str.split(" ")[0].split(" ")[1]

    print(url)

 

    func = None

    for i in url2func:

        if url == i[0]:

            func = i[1]  # 拿到将要执行的函数

            break

    else:

        func = None

 

    if func:

        msg = func(url)  # 执行对应的函数

    else:

        msg = b'<h1>404</h1>'  # 找不到要执行的函数就返回404

 

    # 按照HTTP协议的格式要求 回复消息

    conn.send(b'HTTP/1.1 200 OK ')  # 发送状态行

    conn.send(msg)  # 发送响应体

        conn.close()

 

2、服务器程序和应用程序

11 Jun 18 Django

A.收发信息相关(socket)

B.根据不同的URL返回不同的内容(业务逻辑)

C.字符串替换(动态的网页)

 

自己处理ABC –>Tornado(爬虫常使用)

自己处理BC,第三方处理A ->Django(运维开发常使用)

自己处理B,第三方处理A,C->Flask(Web开发常使用)

 

另一个维度分类:

  1. Django(大而全)
  2. 其他

 

对于真实开发中的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开发环境用的就是这个模块来做服务器。

 

3、wsgiref

利用wsgiref模块来替换我们自己写的web框架的socket server部分

"""

根据浏览器访问的路径的不同,返回不同的内容

将不同页面的处理代码封装到函数中

优化频繁的if判断

返回具体的HTML文件

实现不同的用户得到不同的HTML页面

 

"""

 

import time

from wsgiref.simple_server import make_server

 

 

def home(url):

    s = "this is {} page!".format(url)

    return bytes(s, encoding="utf8")

 

def index(url):

    return b'<h1>index page</h1>'

 

def user(url):

    # 不同的用户得到的页面上显示不同的时间

    c_time = str(time.time())

    with open("user.html", "r") as f:

        data_s = f.read()

        data_s = data_s.replace("@@xx@@", c_time) # 替换后的字符串数据

        return bytes(data_s, encoding="utf8")

 

def login(url):

    with open("login.html", "rb") as f:

        return f.read()

 

# url和将要执行的函数的对应关系

url2func = [

    ("/index", index),

    ("/home", home),

    ("/user", user),

    ("/login", login),

]

 

# 按照wsgiref的要求定义一个run_server函数

def run_server(environ, start_response):

    """

 

    :param environ: 跟请求相关的参数

    :param start_response:

    :return:

    """

    # 设置HTTP响应的状态码和头信息

    start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])

    url = environ['PATH_INFO']  # 取到用户输入的url

 

    func = None

    for i in url2func:

        if url == i[0]:

            func = i[1]  # 拿到将要执行的函数

            break

    else:

        func = None

 

    if func:

        msg = func(url)  # 执行对应的函数

    else:

        msg = b'<h1>404</h1>'  # 找不到要执行的函数就返回404

 

    return [msg, ]

 

if __name__ == '__main__':

    httpd = make_server('127.0.0.1', 8090, run_server)

    print("我在8090等你哦...")

    httpd.serve_forever()

 

4、jinja2

HTML内容中利用一些特殊的符号来替换要展示的数据。 用的特殊符号是自己定义的,其实模板渲染有个现成的工具:jinja2

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

pip install jinja2

 

"""

根据浏览器访问的路径的不同,返回不同的内容

将不同页面的处理代码封装到函数中

优化频繁的if判断

返回具体的HTML文件

实现不同的用户得到不同的HTML页面

"""

 

import time

from wsgiref.simple_server import make_server

from jinja2 import Template

import pymysql

 

def home(url):

    s = "this is {} page!".format(url)

    return bytes(s, encoding="utf8")

 

def index(url):

    return b'<h1>index page</h1>'

 

def user(url):

    # 从数据库里面去到所有的用户信息,

    conn = pymysql.connect(

        host='127.0.0.1',

        port=3306,

        user='root',

        password='123',

        database='db1',

        charset='utf8'

    )

    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

    cursor.execute('select * from user')

    ret = cursor.fetchall()

    print(ret)

    # 在页面上显示出来

    with open("user.html", "r", encoding="utf8") as f:

        data_s = f.read()

        template = Template(data_s)  # 生成一个模板文件实例

        msg = template.render({"user_list": ret})  # 把数据填充到模板里面

        return bytes(msg, encoding="utf8")

 

 

def login(url):

    with open("login.html", "rb") as f:

        return f.read()

 

# url和将要执行的函数的对应关系

url2func = [

    ("/index", index),

    ("/home", home),

    ("/user", user),

    ("/login", login),

]

 

# 按照wsgiref的要求定义一个run_server函数

def run_server(environ, start_response):

    """

 

    :param environ: 跟请求相关的参数

    :param start_response:

    :return:

    """

    # 设置HTTP响应的状态码和头信息

    start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])

    url = environ['PATH_INFO']  # 取到用户输入的url

 

    func = None

    for i in url2func:

        if url == i[0]:

            func = i[1]  # 拿到将要执行的函数

            break

    else:

        func = None

 

    if func:

        msg = func(url)  # 执行对应的函数

    else:

        msg = b'<h1>404</h1>'  # 找不到要执行的函数就返回404

 

    return [msg, ]

 

if __name__ == '__main__':

    httpd = make_server('127.0.0.1', 8090, run_server)

    print("我在8090等你哦...")

    httpd.serve_forever()

 

user.html

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

   <title>Title</title>

    <meta name="viewport" content="width=device-width, initial-scale=1">

</head>

<body>

 

<h1>hello</h1>

<table border="1">

    <thead>

    <tr>

       <th>id</th>

        <th>姓名</th>

        <th>爱好</th>

    </tr>

    </thead>

    <tbody>

    {% for user in user_list %}

    <tr>

       <td>{{user.id}}</td>

       <td>{{user.name}}</td>

       <td>{{user.hobby}}</td>

    </tr>

    {% endfor %}

    </tbody>

</table>

</body>

</html>

 

5、Django

https://www.djangoproject.com/download/

 

A、安装(最新LTS版)

pip3 install django==1.11.11

11 Jun 18 Django

B、创建一个django项目

11 Jun 18 Django

11 Jun 18 Django

11 Jun 18 Django

C、运行一个Django项目

python manage.py runserver 127.0.0.1:8000

or

11 Jun 18 Django

11 Jun 18 Django

D、模版文件和静态文件配置

Template放html

Static(自己命名)放css,js

 

在settings.py中配置

STATIC_URL = '/static/'  # 别名;HTML中使用的静态文件夹前缀

STATICFILES_DIRS = [

os.path.join(BASE_DIR, "css"),  # 静态文件存放位置

os.path.join(BASE_DIR, "js")

]

 

E、Django基础必备三件套

from django.shortcuts import HttpResponse, render, redirect

 

HttpResponse:内部传入一个字符串参数,返回给浏览器。

例如:

def index(request):

    # 业务逻辑代码

    return HttpResponse("OK")

 

render:除request参数外还接受一个待渲染的模板文件和一个保存具体数据的字典参数。将数据填充进模板文件,最后把结果返回给浏览器。(类似于我们上面用到的jinja2)

例如:

def index(request):

    # 业务逻辑代码

    return render(request, "index.html", {"name": "alex", "hobby": ["烫头", "泡吧"]})

 

redirect:接受一个URL参数,表示跳转到指定的URL。

例如:

 

def index(request):

    # 业务逻辑代码

    return redirect("/home/")

 

F、常规步骤

1、创建一个django项目

2、在settings.py中对静态文件进行配置

STATIC_URL = '/static/'

 

STATICFILES_DIRS = [

   os.path.join(BASE_DIR,'css'),

   os.path.join(BASE_DIR,'js')

]

3、将要执行的html文件放入templates文件夹

4、将需要的静态文件放入相应文件夹(js文件放入js文件夹,css文件放入css文件夹)

5、在html文件中导入上述js,css文件时,要注意导入路径

<script src="/static/jquery-3.3.1.min.js"></script>

6、将要执行的html文件封装成函数,添加到urls.py中

    from django.shortcuts import HttpResponse, render, redirect

def login(request):

    return render(request,"批量修改.html")

 

urlpatterns = [

    url(r'^admin/', admin.site.urls),

    url(r'login/',login)

]