zoukankan      html  css  js  c++  java
  • day49:django:wsgrief&模板渲染Jinjia2&django的MTV/MVC框架&创建/启动一个django项目

    目录

    1.自定义web框架wsgiref版

    2.自定义web框架wsgiref版-优化版

    3.模板渲染JinJa2

    4.MTV和MVC框架

    5.django:下载安装&创建启动

    自定义web框架wsgiref版

    1.wsgiref构建服务端

    wsgiref本身就是个web框架,提供了一些固定的功能(请求和响应信息的封装),

    有了wsgiref我们就不需要自己写原生的socket了

    也不需要咱们自己来完成请求信息的提取了

    整体结构和socketserver类似

    2.登录函数逻辑

    登录操作 进入页面为get请求 提交数据是post请求

    def login(environ):
        # 回复login.html
        # environ['QUERY_STRING'] --'username=chao'
        method = environ['REQUEST_METHOD']
        if method == 'GET': # 打开login页面
            with open('login.html', 'rb') as f:
                data = f.read()
            return data
        else:
            print(environ)
            content_length = int(environ.get('CONTENT_LENGTH',0)) # 获取'username=asdf&password=asdf的长度
    
            # environ['wsgi.input']是post对象,对象中内置了read方法,参数是长度,读出来的是字节流,再decode一下,得到字符串
            data = environ['wsgi.input'].read(content_length).decode('utf-8') # environ['wsgi.input']是post对象
    
            #post请求提交过来的数据
            print('请求数据为', data)   #请求数据为 b'username=asdf&password=asdf
    
            # 使用parse_qs的原因:'username=asdf&password=asdf这个字符串把用户名和密码完全切割出来太麻烦
            # parse_qs可以将这个字符串格式化成我们需要的字典,这样的话取值非常方便
            data = parse_qs(data)
            print('格式化之后的数据',data)  #格式化之后的数据 {'username': ['chao'], 'password': ['123']}
    
            # 通过字典轻而易举获取post提交过来的用户名和密码
            uname = data.get('username')
            pwd = data.get('password')
    
            # 调用check函数 检测用户名密码是否正确,返回一个是否成功状态status
            status = check(uname,pwd)
            # 登录成功 跳转到html页面
            if status:
                data = html(environ)
                return data
            # 登录失败 给一个错误提示
            else:
                return b'gunduzi'

    3.application函数逻辑(替代socket)

    def application(environ, start_response):
        '''
        :param environ: 是全部加工好的请求信息,加工成了一个字典,通过字典取值的方式就能拿到很多你想要拿到的信息
        :param start_response: 帮你封装响应信息的(响应行和响应头),注意下面的参数
        :return:
        '''
        path = environ['PATH_INFO']
        print(environ)
        '''
        urlpatterns = [
            ('/', html),
            ('/login', login),
            ('/vip.html', vip),
            ('/spa.ico', ico),
            ('/test.css', css),
            ('/test.js', js),
            ('/2.jpg', jpg),
    
        ]
        '''

       for url in urlpatterns: if url[0] == path: data = url[1](environ) break else: return b'404 page not found' # 封装响应行和响应头的 start_response('200 OK', [('a','1'),]) # print(environ) # print(environ['PATH_INFO']) #输入地址127.0.0.1:8000,这个打印的是'/',输入的是127.0.0.1:8000/index,打印结果是'/index' return [data] httpd = make_server('127.0.0.1', 8001, application) ''' make_server的作用: 将请求信息处理成一个字典 把 [data] 响应到html页面 ''' print('Serving HTTP on port 8001...') # 开始监听HTTP请求: httpd.serve_forever()

    4.创建数据库并插入数据

    如果我们要做一个登陆注册的一个界面,肯定要输入用户名和密码,这时候肯定要涉及数据库的操作了

    so 我们在数据库中创建一些数据

    mysql> create database db1;
    Query OK, 1 row affected (0.00 sec)
    
    mysql> use db1;
    Database changed
    mysql> create table userinfo(id int primary key auto_increment,username char(20) not null unique,password char(20) not null);
    Query OK, 0 rows affected (0.23 sec)
    
    mysql> insert into userinfo(username,password) values('chao','666'),('sb1','222');
    Query OK, 2 rows affected (0.03 sec)
    Records: 2  Duplicates: 0  Warnings: 0
    
    mysql> select * from userinfo;
    +----+----------+----------+
    | id | username | password |
    +----+----------+----------+
    |  1 | chao     | 666      |
    |  2 | sb1      | 222      |
    +----+----------+----------+
    2 rows in set (0.00 sec)

    5.pymysql连接数据库对数据库进行操作

    数据创建好了,我们现在想要用python对数据库进行操作,所以需要pymysql来连接一下

    #创建表,插入数据
    def createtable():
        import pymysql
        conn = pymysql.connect(
            host='127.0.0.1',
            port=3306,
            user='root',
            password='666',
            database='db1',
            charset='utf8'
        )
        cursor = conn.cursor(pymysql.cursors.DictCursor)
        sql = '''
            -- 创建表
            create table userinfo(id int primary key auto_increment,username char(20) not null unique,password char(20) not null);
            -- 插入数据
            insert into userinfo(username,password) values('chao','666'),('sb1','222');
        '''
        cursor.execute(sql)
        conn.commit()
        cursor.close()
        conn.close()

    6.auth登录验证

    现在有数据库了,我们就可以对用户名和密码进行验证了

    在auth函数中传入用户输入的用户名和密码,通过select查询结果确定用户名和面是否正确

    #对用户名和密码进行验证
    def auth(username,password):
        import pymysql
        conn = pymysql.connect(
            host='127.0.0.1',
            port=3306,
            user='root',
            password='123',
            database='db1',
            charset='utf8'
        )
        print('userinfo',username,password)
        cursor = conn.cursor(pymysql.cursors.DictCursor)
        sql = 'select * from userinfo where username=%s and password=%s;'
        res = cursor.execute(sql, [username, password])
        if res:
            return True
        else:
            return False

    7.登录页面-login.html

    在网页上,我们要看到一个用户名和密码的输入框,所以需要创建一个前端html文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <!--如果form表单里面的action什么值也没给,默认是往当前页面的url上提交你的数据,所以我们可以自己指定数据的提交路径-->
    <!--<form action="http://127.0.0.1:8080/auth/" method="post">-->
    <form action="http://127.0.0.1:8080/auth/" method="get">
        用户名<input type="text" name="username">
        密码 <input type="password" name="password">
        <input type="submit">
    </form>
    
    <script>
    
    </script>
    </body>
    </html>

    8.登陆成功的跳转界面

    登录成功后,有一个跳转页面,所以需要创建一个跳转页面的html文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            h1{
                color:red;
            }
        </style>
    </head>
    <body>
    <h1>宝贝儿,恭喜你登陆成功啦</h1>
    
    
    </body>
    </html>

    自定义web框架wsgiref版-优化版

    优化版和上面的版本有什么不同?

    对之前的版本进行优化,将不同的函数按照功能分别写到不同的文件和文件夹中

    下面是文件的一个结构图:

    关于上图的解释

    1.static用于存放一些静态文件

      包括css js icon jpg图片这种文件

    2.template存放前端html文件

    3.auth用来存放一些需要验证的函数

    import pymysql
    
    def check(username, pwd):
        conn = pymysql.connect(
            host='152.136.114.188',
            port=3306,
            user='root',
            password='123456',
            database='django',
            charset='utf8'
        )
        cursor = conn.cursor()
        sql = 'select * from userinfo where username=%s and password=%s;'
        res = cursor.execute(sql, [username, pwd])
        if res:
            return True
        else:
            return False

    4.manage.py是用来实现执行命令的函数

    这样我们在pycharm命令行中通过 python manage.py xxx就可以执行相关命令了

    from models import UserInfo
    from wsgi import run
    
    import sys
    args = sys.argv
    print(args)   #['manage.py', 'migrate']
    print(args[1])
    if args[1] == 'migrate':
       obj = UserInfo()
       obj.create_model()
    elif args[1] == 'runserver':
         ip = args[2]
         port = int(args[3])
         print(ip,port)
         # print(type(port))
         run(ip, port)
    
    
     # python manage.py runserver 127.0.0.1 8001

    5.models.py是和数据库相关的

    主要完成了用python连接mysql的相关配置信息以及python对mysql进行一些增删改查操作用的

    class UserInfo:
    
        def create_model(self):
            import pymysql
    
            conn = pymysql.connect(
                host='152.136.114.188',
                port=3306,
                user='root',
                password='123456',
                database='django',
                charset='utf8'
            )
            cursor = conn.cursor()
    
            sql = '''
                create table userinfo(id int primary key auto_increment, username char(10), password char(10));
    
            '''
            cursor.execute(sql)
            conn.commit()

    6.urls.py是用来确定url路径的,并且通过访问相应的路径,可以执行和路径相关的函数(view)

    import views
    urlpatterns = [
    
        ('/home', views.home),
        ('/login', views.login),
        ('/vip.html', views.vip),
        ('/favicon.ico', views.ico),
        ('/test.css', views.css),
        ('/test.js', views.js),
        ('/2.jpg', views.jpg),
    
    ]

    7.views.py是用来实现主要逻辑的,和项目内容逻辑相关的函数都写在这里面

    def home(environ):
    
        msg = {'name': 'chao', 'hobby': ['女人', 'ddj', '小电影']}
        # with open('./templates/index.html', 'rb') as f:
        #     data = f.read()
        with open('./templates/index.html', 'r', encoding='utf-8') as f:
            data = f.read()
        
        t = Template(data)
        ret = t.render(msg)
    
        return ret.encode('utf-8')

    8.wsgi.py是web框架的服务器, 它代替了socket

    from urls import urlpatterns
    from wsgiref.simple_server import make_server
    
    def run(ip, port):
        # print('xxxxxxxx')
        def application(environ, start_response):
            '''
            :param environ: 是全部加工好的请求信息,加工成了一个字典,通过字典取值的方式就能拿到很多你想要拿到的信息
            :param start_response: 帮你封装响应信息的(响应行和响应头),注意下面的参数
            :return:
            '''
            path = environ['PATH_INFO']
    
            for url in urlpatterns:
                if url[0] == path:
                    data = url[1](environ)
                    break
            else:
                data = b'404 page not found'
    
    
            start_response('200 OK', [('a', '1'), ])
    
            return [data]
    
        httpd = make_server(ip, port, application)
    
        # print('Serving HTTP on port 8001...')
        # 开始监听HTTP请求:
        httpd.serve_forever()

    模板渲染JinJa2

    如果我们想实现一个动态页面

    之前使用的方法是:

    假设以时间为例,在前端页面上显示时间戳(刷新就会显示当前时间戳)

    怎么做到这件事呢?

    def html(environ):
        # 1.创建一个当前时间时间戳
        current_time = str(time.time())
    
        # 2.读出当前的html文件
        with open('./templates/home.html', 'r', encoding='utf-8') as f:
            data = f.read()
        # 3.将文件中的xxoo替换为时间戳
        data = data.replace('xxoo', current_time).encode('utf-8')
        return data

    在home.html中,搞一个字符串xxoo,然后时间戳就能够替换上去了

    <body>
        <!-- 在html文件中,写一个标签,其中的内容有xxoo -->
        <h1>皇家赌场--xxoo</h1>
        <a href="http://127.0.0.1:8002/vip.html">会员中心</a>
        <img src="2.jpg" alt="">
        <div class="c1" id="d1"></div>
    </body>

    其实,这种行为从专业角度老说,叫做模板渲染

    这个过程其实就是HTML模板渲染数据

    本质上就是HTML内容中利用一些特殊的符号来替换要展示的数据。

    我这里用的特殊符号是我定义的

    其实模板渲染有个现成的工具:JinJa2

    用JinJa2实现动态界面

    from jinja2 import Template
    
    
    def index():
        with open("index2.html", "r",encoding='utf-8') as f:
            data = f.read()
        template = Template(data)  # 生成模板文件
        ret = template.render({"name": "于谦", "hobby_list": ["烫头", "泡吧"]})  # 把数据填充到模板里面
        return [bytes(ret, encoding="utf8"), ]

    在JinJa2中 特殊符号就是{{  }} or {%  %}

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="x-ua-compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>Title</title>
    </head>
    <body>
        <h1>姓名:{{name}}</h1>
        <h1>爱好:</h1>
        <ul>
            {% for hobby in hobby_list %}
            <li>{{hobby}}</li>
            {% endfor %}
        </ul>
    </body>
    </html>

    上面.py中的数据是我们手动写的

    当然我们也可以从数据库中获取数据,但是前提一定要配置用pymysql配置好数据库哦

    MTV和MVC框架

    MVC框架

     Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接受用户的输入调用模型和视图完成用户的请求,其示意图如下所示:

    MTV框架

     Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是指:

    • M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
    • T 代表模板 (Template):负责如何把页面展示给用户(html)。
    • V 代表视图(View):   负责业务逻辑,并在适当时候调用Model和Template。

      除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:

      

      一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求回去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。

    django:下载安装&创建启动

    1.下载django

    pip3 install django==1.11.9

    2.创建一个django的project

    django-admin startproject mysite   # 创建了一个名为"mysite"的Django 项目:

    当我们执行完这条指令后 ,会出现如下一堆文件

    这些文件的作用:

    • manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库,启动关闭项目与项目交互等,不管你将框架分了几个文件,必然有一个启动文件,其实他们本身就是一个文件。
    • settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
    • urls.py ----- 负责把URL模式映射到应用程序。
    • wsgi.py ---- runserver命令就使用wsgiref模块做简单的web server,后面会看到renserver命令,所有与socket相关的内容都在这个文件里面了,目前不需要关注它。

    3.创建django APP应用

    刚才我们只是创建了一个django项目,但是里面并没有之前所提到的models.py views.py这些文件

    这是因为我们只是创建了django项目,并没有创建一个django的app

    所以这个app需要我们执行一条指令去创建

    python manage.py startapp blog2  #创建一个django应用 每个应用的目录下都有自己的views.py视图函数和models.py数据库操作相关的文件

    当我们执行完这条指令后,会发现文件夹多了几个文件

      

    我们现在只需要看其中两个文件

        models.py :之前我们写的那个名为model的文件就是创建表用的,这个文件就是存放与该app(应用)相关的表结构的

        views.py    :存放与该app相关的视图函数的

          其他的先不用管,以后会知道的

    4.启动django项目

    python manage.py runserver 8080   # python manage.py runserver 127.0.0.1:8080,本机就不用写ip地址了 如果连端口都没写,默认是本机的8000端口

    这样我们的django就启动起来了。当我们访问:http://127.0.0.1:8080/时就可以看到:

           

    这是django里自己写的一个html文件,当看到这个页面就说明,我们的django启动成功了

  • 相关阅读:
    vpp编写plugin
    vrf 命令
    vxlan + 多个vrf
    dpdk helloworld
    Go函数高级
    Go_defer
    Go递归函数
    Go作用域
    Go函数
    Go字符串
  • 原文地址:https://www.cnblogs.com/libolun/p/13641643.html
Copyright © 2011-2022 走看看