WebFramework-Basis-1st


周六,多云,记录生活分享点滴

参考博客:

推荐博客:https://www.zmrenwu.com/courses/hellodjango-blog-tutorial/

Django 1.1

web框架

框架 framework

  • 特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统

  • 简单地说,就是你用别人搭建好的舞台来做表演

对于所有的Web应用,本质上是一个socket服务端;用户的浏览器是一个socket客户端。

import socket
?
def handle_request(client):
?
    buf = client.recv(1024)
    client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8"))
    client.send("

Hello, yuan

".encode("utf8")) ? def main(): ? sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost',8001)) sock.listen(5) ? while True: connection, address = sock.accept() handle_request(connection) connection.close() ? if __name__ == '__main__': ? main()

最简单的Web应用:

  • 先把HTML用文件保存好,

  • 用一个现成的HTTP服务器软件,接收用户请求,

  • 从文件中读取HTML,返回

如果要动态生成HTML,需要把上述步骤自己来实现:

  • 底层代码由专门的服务器软件实现,

  • 用Python专注于生成HTML文档

  • 需要统一的接口(WSGI:Web Server Gateway Interface),用Python编写Web业务

-- -- -- -- -- -- -- -- -- -- web框架制作步骤 -- -- -- -- -- -- -- -- -- --

step 1

from wsgiref.simple_server import make_server
?
?
def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'

Hello, web!

'] ? ? httpd = make_server('', 8080, application) ? print('Serving HTTP on port 8000...') # 开始监听HTTP请求: httpd.serve_forever()

注意:

整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,
我们只负责在更高层次上考虑如何响应请求就可以了。
?
application()函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器,我们可以挑选一个来用。
?
Python内置了一个WSGI服务器,这个模块叫wsgiref    
    
application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:
?
        //environ:一个包含所有HTTP请求信息的dict对象;
        
        //start_response:一个发送HTTP响应的函数。
?
在application()函数中,调用:
?
start_response('200 OK', [('Content-Type', 'text/html')])
?
就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。
start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每
个Header用一个包含两个str的tuple表示。
?
通常情况下,都应该把Content-Type头发送给浏览器。其他很多常用的HTTP Header也应该发送。
?
然后,函数的返回值b'

Hello, web!

'将作为HTTP响应的Body发送给浏览器。 ? 有了WSGI,我们关心的就是如何从environ这个dict对象拿到HTTP请求信息,然后构造HTML, 通过start_response()发送Header,最后返回Body。

step 2

print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])
    f1=open("index1.html","rb")
    data1=f1.read()
    f2=open("index2.html","rb")
    data2=f2.read()
?
    if path=="/yuan":
        return [data1]
    elif path=="/alex":
        return [data2]
    else:
        return ["

404

".encode('utf8')]

step 3

from wsgiref.simple_server import make_server
?
def f1():
    f1=open("index1.html","rb")
    data1=f1.read()
    return [data1]
?
def f2():
    f2=open("index2.html","rb")
    data2=f2.read()
    return [data2]
?
def application(environ, start_response):
?
    print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])
?
?
    if path=="/yuan":
        return f1()
?
    elif path=="/alex":
        return f2()
?
    else:
        return ["

404

".encode("utf8")] ? ? httpd = make_server('', 8502, application) ? print('Serving HTTP on port 8084...') ? # 开始监听HTTP请求: httpd.serve_forever()

step 4

from wsgiref.simple_server import make_server
?
?
def f1(req):
    print(req)
    print(req["QUERY_STRING"])
?
    f1=open("index1.html","rb")
    data1=f1.read()
    return [data1]
?
def f2(req):
?
    f2=open("index2.html","rb")
    data2=f2.read()
    return [data2]
?
import time
?
def f3(req):        #模版以及数据库
?
    f3=open("index3.html","rb")
    data3=f3.read()
    times=time.strftime("%Y-%m-%d %X", time.localtime())
    data3=str(data3,"utf8").replace("!time!",str(times))
?
?
    return [data3.encode("utf8")]
?
?
def routers():
?
    urlpatterns = (
        ('/yuan',f1),
        ('/alex',f2),
        ("/cur_time",f3)
    )
    return urlpatterns
?
?
def application(environ, start_response):
?
    print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])
?
?
    urlpatterns = routers()
    func = None
    for item in urlpatterns:
        if item[0] == path:
            func = item[1]
            break
    if func:
        return func(environ)
    else:
        return ["

404

".encode("utf8")] ? httpd = make_server('', 8518, application) ? print('Serving HTTP on port 8084...') ? # 开始监听HTTP请求: ? httpd.serve_forever()

 

MVC和MTV模式

MVC模式:

将web应用分为

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

  • 控制器(C):控制器(C)接受用户的输入调用模型和视图完成用户的请求

  • 视图(V):视图负责与用户的交互(页面)

三层之间以一种插件形式,松耦合的方式连接在一起。

Django的MTV模式也是各组件之间为了保持松耦合关系,在定义上有点不同

Django的MTV分别代表:

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

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

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

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

 

django的流程和命令行工具

详情参考:

django实现流程

    # 安装:pip3 install django
       添加环境变量

    # 1  创建project
       django-admin startproject mysite

       ---mysite
          ---settings.py
          ---url.py
          ---wsgi.py

       ---- manage.py(启动文件)  

    # 2  创建APP       
       python mannage.py startapp  app01

    # 3  settings配置
    
       TEMPLATES

       STATICFILES_DIRS=(
            os.path.join(BASE_DIR,"statics"),
       )

       STATIC_URL = '/static/' 
       #  我们只能用 STATIC_URL,但STATIC_URL会按着你的STATICFILES_DIRS去找
    
    # 4  根据需求设计代码
       url.py
       view.py

    # 5  使用模版
       render(req,"index.html")   

    # 6  启动项目
       python manage.py runserver  127.0.0.1:8090

    # 7  连接数据库,操作数据
       model.py

django的命令行工具

  • django-admin.py 是Django的一个用于管理任务的命令行工具,

  • manage.py是对django-admin.py的简单包装,每一个Django Project里都会有一个mannage.py

1.创建一个django工程

django-admin startproject mysite

当前目录下会生成一个 mysite的工程,目录结构如下:

  • manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库等。

  • settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。

  • urls.py ----- 负责把URL模式映射到应用程序。

2.在mysite目录下创建app应用

python manage.py startapp blog

3.启动django项目

python manage.py runserver 8080 # ip:端口,默认本地ip

当我们访问:http://127.0.0.1:8080/ 时就可以看到:

4.生成同步数据库的脚本

python manage.py makemigrations  

同步数据库: python manage.py migrate

注意:在开发过程中,数据库同步误操作之后,难免会遇到后面不能同步成功的情况,解决这个问题的一个简单粗暴方法是把migrations目录下的脚本(除__init__.py之外)全部删掉,再把数据库删掉之后创建一个新的数据库,数据库同步操作再重新做一遍。

5.访问指定网址

当我们访问http://127.0.0.1:8080/admin/时,会出现

所以我们需要为进入这个项目的后台创建超级管理员:python manage.py createsuperuser设置好用户名和密码后便可登录

6.清空数据库

python manage.py flush

7.查询某个命令的详细信息

django-admin.py  help startapp

admin 是Django 自带的一个后台数据库管理系统。

8.启动交互界面

python manage.py shell

这个命令和直接运行 python 进入 shell 的区别是:你可以在这个 shell 里面调用当前项目的 models.py 中的 API,对于操作数据,还有一些小测试非常方便。

9.查看详细列表

终端上输入以下命令,可以看到详细的列表,在忘记子名称的时候特别有用

python manage.py

实例练习1-提交数据并展示

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
<h1>创建个人信息h1>
?
<form action="/userInfor/" method="post">
?
    <p>姓名<input type="text" name="username">p>
    <p>性别<input type="text" name="sex">p>
    <p>邮箱<input type="text" name="email">p>
    <p><input type="submit" value="submit">p>
?
form>
?
<hr>
?
<h1>信息展示h1>
?
<table border="1">
?
    <tr>
        <td>姓名td>
        <td>性别td>
        <td>邮箱td>
    tr>
    {% for i in info_list %}
?
        <tr>
            <td>{{ i.username }}td>
            <td>{{ i.sex }}td>
            <td>{{ i.email }}td>
        tr>
?
    {% endfor %}
?
table>
?
body>
html>
?
?
-----------------------url.py---------------------------------------
url(r'^userInfor/', views.userInfor)
?
-----------------------views.py--------------------------------------
?
info_list=[]
?
def userInfor(req):
?
    if req.method=="POST":
        username=req.POST.get("username",None)
        sex=req.POST.get("sex",None)
        email=req.POST.get("email",None)
?
        info={"username":username,"sex":sex,"email":email}
        info_list.append(info)
?
    return render(req,"userInfor.html",{"info_list":info_list})

实例练习2-提交数据并展示(数据库)

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
<h1>创建个人信息h1>
?
<form action="/userInfor/" method="post">
?
    <p>姓名<input type="text" name="username">p>
    <p>性别<input type="text" name="sex">p>
    <p>邮箱<input type="text" name="email">p>
    <p><input type="submit" value="submit">p>
?
form>
?
<hr>
?
<h1>信息展示h1>
?
<table border="1">
?
    <tr>
        <td>姓名td>
        <td>性别td>
        <td>邮箱td>
    tr>
    {% for i in info_list %}
?
        <tr>
            <td>{{ i.username }}td>
            <td>{{ i.sex }}td>
            <td>{{ i.email }}td>
        tr>
?
    {% endfor %}
?
table>
?
body>
html>
?
?
----------------------------------------------models.py
from django.db import models
?
# Create your models here.
?
?
class UserInfor(models.Model):
?
    username=models.CharField(max_length=64)
    sex=models.CharField(max_length=64)
    email=models.CharField(max_length=64)
?
----------------------------------------------views.py
?
from django.shortcuts import render
?
from app01 import models
# Create your views here.
?
?
def userInfor(req):
?
    if req.method=="POST":
        u=req.POST.get("username",None)
        s=req.POST.get("sex",None)
        e=req.POST.get("email",None)
?
?
       #---------表中插入数据方式一
            # info={"username":u,"sex":e,"email":e}
            # models.UserInfor.objects.create(**info)
?
       #---------表中插入数据方式二
        models.UserInfor.objects.create(
            username=u,
            sex=s,
            email=e
        )
?
        info_list=models.UserInfor.objects.all()
?
        return render(req,"userInfor.html",{"info_list":info_list})
?
    return render(req,"userInfor.html")

 

Setting文件配置

参考博客:

方法一

静态文件在单独的app下:如 /app01/static/app01/JS/jquery-2.1.4.min.js

(其中蓝色app01目录为必须,但可改其他名字,static文件夹也可改其他名字)

# index.html
{% load static %}

setting文件设置: (其中app01为项目名字,static为保存静态文件的文件夹。)

STATIC_URL = '/whattttt/'   # 前端使用前缀
 
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,'app01','static'),
)

方法二(同上述setting配置)

# index.html

方法三(使用别名的形式)

# index.html
{% load static %}

setting文件设置

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

补充:

如果不想每次在模版中加载静态文件都使用 {% load static%}

可以在settings.py中的 TEMPLATES/OPTIONS添加'builtins':['django.templatetags.static']

TEMPLATES = [
  {
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [os.path.join(BASE_DIR, 'templates')]
    ,
    'APP_DIRS': True,
    'OPTIONS': {
      'context_processors': [
        'django.template.context_processors.debug',
        'django.template.context_processors.request',
        'django.contrib.auth.context_processors.auth',
        'django.contrib.messages.context_processors.messages',
      ],
      #添加在这个位置
      'builtins' : [
        'django.templatetags.static'
      ],
    },
  },
]

补充:pycharm创建django项目

主要总结一下在pycharm中进行django的创建遇到的问题

对于django的安装和pipenv虚拟环境的设置可参考:https://www.zmrenwu.com/courses/hellodjango-blog-tutorial/materials/59/

1.如果选择pipenv虚拟环境下创建django项目时,情况如下图

2.然后进行创建中

3.当在运行过程中如果出现这下图类似的错误

4.可以尝试以下建议(https://pypi.tuna.tsinghua.edu.cn/simple

5.修改完成后

6.再次重新创建django,现在无法打开,静静等待最下面的蓝色字母运行完成(我的电脑需要运行一两分钟,有的是秒建,不知道什么原因)

7.然后就可以正常运行django了

8.总结

需要修改文件夹下Pipfile文件中sours下的url,修改为 https://pypi.tuna.tsinghua.edu.cn/simple

在此非常感谢群里的小伙伴提供的帮助,折腾了很久,终于可以继续学习了