• [Python自学] day-18 (2) (MTV架构、Django框架、模板语言)


    一、实现一个简单的Web服务器

    使用Python标准库提供的独立WSGI服务器来实现MVC架构。

    首先,实现一个简单的Web服务器:

    from wsgiref.simple_server import make_server
    
    
    # 每当一个请求连接,这个函数被调用一次
    def RunServer(environ, start_response):
        # 返回响应头、状态等
        start_response('200 OK', [('Content-Type', 'text/html')])
        # 返回响应体数据
        return ['<h1>Hello World</h1>'.encode('utf-8'), ]
    
    
    def main():
        # 创建一个服务器,监听端口为8000,绑定运行函数为RunServer()
        httpd = make_server('', 8000, RunServer)
        print('Servering HTTP in port 8000..')
        # 无线循环
        httpd.serve_forever()
    
    
    if __name__ == '__main__':
        main()

    添加处理URL的功能:

    from wsgiref.simple_server import make_server
    import time
    
    
    # 对应'/index'的处理函数
    def handle_index():
        return ["<h1>Index Page...</h1>".encode('utf-8'), ]
    
    
    # 对应'/register'的处理函数
    def handle_register():
        return ["<h1>Register Page...</h1>".encode('utf-8'), ]
    
    
    # 对应'/date'的处理函数
    def handle_date():
        return [("<h1>Date:" + str(time.time()) + "</h1>").encode('utf-8'), ]
    
    
    # 全局字典,手工添加映射关系
    URL_DICT = {
        '/index': handle_index,
        '/register': handle_register,
        '/date': handle_date
    }
    
    
    # 每当一个请求连接,这个函数被调用一次
    def RunServer(environ, start_response):
        # 返回响应头、状态等
        start_response('200 OK', [('Content-Type', 'text/html')])
    
        # 检查字典中是否存在映射关系,如果有则调用对应的函数,如果没有则返回404
        current_url = environ['PATH_INFO']
        func = None
        if current_url in URL_DICT:
            func = URL_DICT[current_url]
        if func:
            return func()
        else:
            return ['<h1>404 Error Page..</h1>'.encode('utf-8'), ]
    
    
    def main():
        # 创建一个服务器,监听端口为8000,绑定运行函数为RunServer()
        httpd = make_server('', 8000, RunServer)
        print('Servering HTTP in port 8000..')
        # 无线循环
        httpd.serve_forever()
    
    
    if __name__ == '__main__':
        main()

    上述代码添加了处理URL的功能,可以根据不同的URL返回不同的数据。

    主要的关键点:

    1.使用一个全局的字典来存放URL和处理函数之间的映射关系(注意,这里的映射关系是写死的,也就是说我们要添加一个页面,就得手工往字典中添加一个映射关系)

    2.每个URL使用一个独立的函数进行处理

    我们可以通过处理函数读取index.html文件中的内容,然后将其返回

    对handle_index()进行修改:

    # 对应'/index'的处理函数
    def handle_index():
        data = b''
        with open('index.html', 'rb') as f:
            data = f.read()
        return [data, ]

    添加一个index.html文件:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Index Page</title>
    </head>
    <body>
        <h1>This is @user Index Page...</h1>
    </body>
    </html>

    这里的@user可以用数据库读取的内容来替换。

    二、MVC架构

    我们参考第一节中的代码,将其修改为MVC架构。

    修改项目的目录结构,添加View、Controller和Model三个目录:

    Controller:用于存放业务处理逻辑代码,例如前面的handle_index()等。功能例如读取Html文件,替换数据,返回数据等。

    Model:用于存放数据库操作等代码。这些代码用于读取数据库数据,并将数据返回给Controller。

    View:用于存放前端页面文件,例如Html等。主要是Html模板。

    我们将index.html这类静态文件放入View目录中。

    将handle处理函数全部分离到handler.py中,然后放到Controller中:

    import time
    from Model import read_db
    
    
    # 对应'/index'的处理函数
    def handle_index():
        data = b''
        with open('Template/index.html', 'rb') as f:
            data = f.read()
    
        user = read_db.get_user()
        print(user)
       # 将index.html中的@user替换为从数据库中获取的数据,这里例如"Leo" data
    = data.replace(b"@user", user.encode('utf-8')) return [data, ] # 对应'/register'的处理函数 def handle_register(): return ["<h1>Register Page...</h1>".encode('utf-8'), ] # 对应'/date'的处理函数 def handle_date(): return [("<h1>Date:" + str(time.time()) + "</h1>").encode('utf-8'), ]

    这样,将所有的文件分类放置。将整个项目划分为MVC三个层面,叫做MVC架构

    三、MTV架构

    对应MVC架构,还有一种叫做MTV架构,实际上他们是一样的:

    架构名称 数据库处理 模板文件 业务处理
    MVC Model View Controller
    MTV Model Template View

    如上表所示,MVC和MTV架构只是名字的对应关系不一样。

    在MTV中,html文件属于Template,而业务处理叫做View。

    通过修改项目目录结构,将MVC修改为MTV结构:

    四、安装Django

    使用PYTHON_HOME/Scripts/pip.exe来安装Django:

    # 使用清华源安装django
    pip install django -i https://pypi.tuna.tsinghua.edu.cn/simple

    将PYTHON_HOME/Scripts添加到环境变量:

    使用django-admin命令来创建一个django项目:

    D:>django-admin startproject firstsite

    其中firstsite是django项目名称,我们在D盘根目录下执行命令,项目则存在于这个目录下。

    进入生成的firstsite目录,我们可以看到:

    使用manage.py运行django程序:

    D:firstsite>python manage.py runserver 127.0.0.1:8001
    Watching for file changes with StatReloader
    Performing system checks...
    
    System check identified no issues (0 silenced).
    
    You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
    Run 'python manage.py migrate' to apply them.
    December 16, 2019 - 13:25:34
    Django version 3.0, using settings 'firstsite.settings'
    Starting development server at http://127.0.0.1:8001/
    Quit the server with CTRL-BREAK.

    访问127.0.0.1:8001,可以看到以下页面,表示django运行成功:

    除了使用django-admin命令创建django程序,还可以直接在Pycharm中创建:

    Pycharm会创建一个一样的django程序:

    点击Pycharm右上角的运行按钮即可运行django:

     注意,这里一定要选择项目名运行,否则运行报错。如果要修改运行的host和port,则进入Edit Configurations中进行修改。

    You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
    Run 'python manage.py migrate' to apply them.
    December 16, 2019 - 14:03:12
    Django version 3.0, using settings 'secondsite.settings'
    Starting development server at http://127.0.0.1:8000/
    Quit the server with CTRL-BREAK.

    五、django目录介绍

    1.用Pycharm打开已经创建好的django程序

    2.django程序目录结构

    firstsite
        -- firstsite   # 对整个程序进行配置的目录
            -- __init__
            -- settings.py   # 配置文件
            -- urls.py   # URL对应关系
            -- wsgi.py   # 遵循WSGI规范,默认使用的是wsgiref,上线的话要使用uwsgi + nginx
        -- db.sqlite3
        -- manage.py   # 管理Django程序,例如创建一个APP:python manage.py startapp xxx
                                           django的ORM:python manage.py makemigrations
                                                        python manage.py migrate

    六、django中的APP

    1.APP概念

    我们创建一个django工程以后,我们可以创建多个APP,每个APP代表着一个子模块,如图:

    这个运维平台看做一个django project,而下面的 资产、配管、私有云等都是一个APP。

    2.创建一个APP

    在Pycharm中使用命令行来创建(Pycharm最下方可以选择Terminal页签):

    执行命令:

    d:Dev_appsAnaconda5.3.0python.exe manage.py startapp cmdb

    其中,cmdb是APP名称。

    当然,我们也可以使用windows cmd命令窗口执行。

    创建完毕后,我们可以看到生成了一个cmdb目录:

    3.测试使用APP

    在cmdb APP中,我们找到Views文件:

    然后在其中添加请求处理函数:

    from django.shortcuts import render
    
    # Create your views here.
    from django.shortcuts import HttpResponse
    
    
    # /cmdb.html请求的处理函数
    def cmdb_home(request):
        return HttpResponse("<h1>CMDB home page..</h1>")

    在secondsite/urls.py中添加一条映射关系:

    from cmdb import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('cmdb.html/', views.cmdb_home),
    ]

    运行django程序,访问页面:

    七、APP的目录结构

    1.miragtions目录:

    在 [Python自学] day-12 (Mysql、事务、索引、ORM) 中,我们使用过ORM框架 SQLAlchemy。

    在SQLAlchemy中,我们可以创建表、增删改查数据等,但无法对表结构进行修改

    但在django框架中,他所提供的ORM功能非常厉害,可以提供很细致化的操作,例如删除表的列、修改列的数据类型、数据长度等等。

    我们在某个Django APP目录中可以看到一个叫做migrations的目录

    这个目录是用来记录数据库操作的,当我们做了修改表结构等数据库操作后,django会自动在migrations目录中生成记录,我们无法人工干预。

    2. admin.py

    该目录是django为我们提供的数据库后台管理,可以用很少的代码实现一个功能比较完整的后台管理页面。效果如下:

    默认情况下,django为我们提供了一个轻量级数据库Sqlite3:

    3.apps.py

    用于配置当前APP

    4.models.py

    就是django给我们提供的ORM,我们在里面写指定的类,然后通过manage.py makemigrations和manage.py migrate就可以创建表和修改表结构(会在migrations目录中产生记录文件)。

    5.tests.py

    单元测试

    6.views.py

    业务逻辑代码

    八、实现简单的login页面

    在cmdb APP中实现简单的Login页面。

    1.在urls.py中添加相应的映射关系

    from cmdb import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('login/', views.login),
    ]

    2.在工程的根目录下创建一个目录叫templates

    3.在templates目录下创建login.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Login</title>
        <style>
            label{
                width: 80px;
                text-align: right;
                display: inline-block;
            }
        </style>
    </head>
    <body>
        <form action="/login" method="post">
            <p>
                <label for="username">用户名:</label>
                <input id="username" type="text" />
            </p>
            <p>
                <label for="password">密码:</label>
                <input id="password" type="password"/>
                <input type="submit" value="提交"/>
            </p>
        </form>
    </body>
    </html>

    4.在cmdb/views.py中写业务逻辑代码

    from django.shortcuts import render
    
    # Create your views here.
    from django.shortcuts import HttpResponse
    
    
    def login(request):
        f = open("templates/login.html", 'r', encoding="utf-8")
        data = f.read()
        return HttpResponse(data)

    在业务代码中,我们使用open()打开html文件,读取内容并返回给客户端。

    但是如果我们有很多页面,则每个都要手工打开文件读取。Django为我们提供了相应的处理方法。

    5.使用render来打开html模板

    修改views.py中的业务逻辑代码:

    from django.shortcuts import render
    
    # Create your views here.
    from django.shortcuts import HttpResponse
    from django.shortcuts import render
    
    
    def login(request):
        return HttpResponse(render(request, 'login.html'))

    从django.shortcuts中导入render,然后使用render来读取templates/login.html文件。

    注意:这里我们没有使用templates/login.html路径,而是直接使用login.html。render()方法之所以能直接找到login.html文件,是因为在setting.py文件中对模板路径的默认配置就是templates。如下:

    # setting.py文件
    
    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',
                ],
            },
        },
    ]

    配置文件中的BASE_DIR就是django工程的根目录(这里是secondsite)。这里将BASE_DIR和'templates'拼接在一起作为模板的DIR。

    6.访问/login

    九、静态文件处理

    当我们要在项目中添加静态文件是,例如css、js、图片等。

    1.在项目根目录下创建目录static

    2.将需要的静态文件拷贝到static目录中

    其中commons.css内容如下:

    .common{
        background-color: #eeeeee;
    }

    3.在login.html中使用css文件和jQuery

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Login</title>
        <link rel="stylesheet" href="/static/commons.css"/>
        <style>
            label{
                width: 80px;
                text-align: right;
                display: inline-block;
            }
        </style>
    </head>
    <body class="common">
        <form action="/login" method="post">
            <p>
                <label for="username">用户名:</label>
                <input id="username" type="text" />
            </p>
            <p>
                <label for="password">密码:</label>
                <input id="password" type="password"/>
                <input type="submit" value="提交"/>
            </p>
        </form>
        <script src="/static/jquery-1.12.4.js"></script>
    </body>
    </html>

    4.访问/login报错404

    当页面在请求/static/commons.css和/static/jquery-1.12.4.js时报404错误,说明资源为找到。

    有两种解决方法:

    1) 在urls中添加映射关系(可以实现,但不能这么做,静态文件django可以专门处理)

    2) 在setting中配置静态文件的路径(正解)

    5.在settings中配置静态文件路径

    在settings.py配置文件的最后添加以下代码:

    STATICFILES_DIRS = (
        os.path.join(BASE_DIR, 'static'),  # 这里必须有逗号
    )

    6.再次访问/login

    页面访问正常,并且background-color已经变为灰色(commons.css中指定的)。

    7.填写表单并提交报错

     这是因为我们的表单提交的目的地是/login。

    解决方法一:urls.py中的匹配字符串为"login/",所以表单提交地址应该修改为action="/login/"

    解决方法二:urls.py中修改为"login"action="/login"

    这样对应起来,才能匹配。

    8.再次提交报错

    这是CSRF(跨站点请求伪造)错误。参照下一节django配置,将CSRF相关配置注释。

    十、Django配置

    以上章节中已经描述了django的两项配置:

    1)对templates路径的配置

    2)对static路径的配置

    1.对CSRF进行配置:

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        #'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

    在settings.py中将csrf相关的配置项注释掉。

    2.配置Django时区:

    如果不进行时间配置,Django默认时间比上海时间延后8小时。

    在setting中配置时间:

    # 将时区修改为上海
    # TIME_ZONE = 'UTC'
    TIME_ZONE = 'Asia/Shanghai'
    
    #将USE_TZ修改为false
    # USE_TZ = True
    USE_TZ = False

    十一、获取请求参数

    在我们实现的请求处理业务逻辑代码中,我们可以获取来自客户端请求的所有参数:

    from django.shortcuts import render
    
    # Create your views here.
    from django.shortcuts import HttpResponse
    from django.shortcuts import render
    
    
    def login(request):
        return HttpResponse(render(request, 'login.html'))

    这些请求参数,都通过 client-->Webserver-->wsgi-->django 将其作为函数参数传递到被调用的login()函数中。

    我们通过request就可以获取到客户端的所有参数

    1.通过参数判断请求类型

    # cmdb views.py
    
    from django.shortcuts import render
    
    # Create your views here.
    from django.shortcuts import HttpResponse
    from django.shortcuts import render
    
    
    def login(request):
        if request.method == 'POST':
            print("Post")
        elif request.method == 'GET':
            print('Get')
        return HttpResponse(render(request, 'login.html'))

    当我们第一次访问/login时,后台会打印"GET",当我们提交表单是,后台会打印"POST"。

    2.获取POST提交的数据

    POST提交的数据是以字典形式组织的,所以,首先要在html表单中为<input>标签指定name属性作为key。

    <body class="common">
        <form action="/login/" method="post">
            <p>
                <label for="username">用户名:</label>
                <input id="username" type="text" name="user"/>
            </p>
            <p>
                <label for="password">密码:</label>
                <input id="password" type="password" name="pwd"/>
                <input type="submit" value="提交"/>
            </p>
        </form>
        <script src="/static/jquery-1.12.4.js"></script>
    </body>

    然后在后台通过request获取POST数据:

    from django.shortcuts import render
    
    # Create your views here.
    from django.shortcuts import HttpResponse
    from django.shortcuts import render
    
    
    def login(request):
        if request.method == 'POST':
            # username = request.POST['user']  # 尽量不要用这种方式,因为user如果不存在,则会报错
            username = request.POST.get('user', None)
            password = request.POST.get('pwd', None)
            print("username : %s
    password : %s" % (username, password))
        elif request.method == 'GET':
            print('Get')
        return HttpResponse(render(request, 'login.html'))

    3.验证数据并跳转

    from django.shortcuts import render
    
    # Create your views here.
    from django.shortcuts import HttpResponse
    from django.shortcuts import render
    from django.shortcuts import redirect
    
    
    def login(request):
        if request.method == 'POST':
            username = request.POST.get('user', None)
            password = request.POST.get('pwd', None)
            # 验证user和pwd,如果正确,则跳转到www.baidu.com
            if username == 'leokale' and password == '123456':
                return redirect('http://www.baidu.com')
        elif request.method == 'GET':
            print('Get')
        return HttpResponse(render(request, 'login.html'))

    这里的跳转要使用return redirect("http://www.baidu.com")

    4.提交错误数据,返回错误消息

    以下代码实现了错误消息提示,但页面会刷新(实际上是返回了一个新的页面,包含了错误信息),以后可以使用Ajax异步请求来实现错误提示。

    1)在html中,添加错误信息的标签

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Login</title>
        <link rel="stylesheet" href="/static/commons.css"/>
        <style>
            label{
                width: 80px;
                text-align: right;
                display: inline-block;
            }
            .error_span{
                color: red;
            }
        </style>
    </head>
    <body class="common">
        <form action="/login/" method="post">
            <p>
                <label for="username">用户名:</label>
                <input id="username" type="text" name="user"/>
                <span class="error_span">{{ user_error }}</span>
            </p>
            <p>
                <label for="password">密码:</label>
                <input id="password" type="password" name="pwd"/>
                <input type="submit" value="提交"/>
                <span class="error_span">{{ pwd_error }}</span>
            </p>
        </form>
        <script src="/static/jquery-1.12.4.js"></script>
    </body>
    </html>

    2)验证user和pwd错误时,django自动替换错误信息

    from django.shortcuts import render
    
    # Create your views here.
    from django.shortcuts import HttpResponse
    from django.shortcuts import render
    from django.shortcuts import redirect
    
    
    def login(request):
        if request.method == 'POST':
            username = request.POST.get('user', None)
            password = request.POST.get('pwd', None)
            # 验证user和pwd,如果正确,则跳转到www.baidu.com
            if username == 'leokale' and password == '123456':
                return redirect('http://www.baidu.com')
    
            user_error_msg = ''
            pwd_error_msg = ''
            if username != 'leokale':
                user_error_msg = "账号不存在"
            if password != '123456':
                pwd_error_msg = "密码不正确"
            # 当user或pwd错误时,django自动使用第三个参数字典中的数据对html中的{{ xxx }}进行替换
            return HttpResponse(render(request, 'login.html', {"user_error": user_error_msg, "pwd_error": pwd_error_msg}))
    
        elif request.method == 'GET':
            print('Get')
        return HttpResponse(render(request, 'login.html'))

    访问/login,提交错误的数据,效果如下:

    十二、实现简单后台管理功能(利用Django模板语言)

    请求后台管理页面:http://127.0.0.1/home

    1.在urls.py中添加映射关系

    from cmdb import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('login', views.login),
        path('home', views.home),  # 后台管理页面映射,映射到cmdb.views.home方法
    ]

    2.home.html页面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Home</title>
    </head>
    <body style="margin: 0">
        <div style="height: 48px;background-color: #dddddd"></div>
        <div>
            <!-- 如果用户点击添加按钮,则使用post提交表单 -->
            <form action="/home" method="post">
                <input type="text" name="username"/>
                <input type="text" name="email"/>
                <input type="text" name="gender"/>
                <input type="submit" value="添加"/>
            </form>
        </div>
        <div>
            <!-- 在table中使用模板语言进行循环,获取user_list中的数据(来自后台render函数的第三个参数) -->
            <table>
                {% for row in user_list %}
                    <tr>
                        <td>{{ row.username }}</td>
                        <td>{{ row.email }}</td>
                        <td>{{ row.gender }}</td>
                    </tr>
                {% endfor %}
            </table>
        </div>
    </body>
    </html>

    在前台html代码中,<table>标签中的数据是动态生成的(来自后台读取全局列表的数据,模拟数据库操作),所以在render返回home.html页面数据时要对<table>的内容进行替换。

    这里使用模板语言,{% %}中使用循环语句{{ }}中进行取值

    3.在cmdb APP的views.py中写请求处理函数

    # 全部列表,用于用户数据(模拟数据库)
    USER_LIST = [
        {'username': 'Alex', 'email': 'alex@163.com', 'gender': 'Male'},
    ]
    
    
    # 后台管理页面
    def home(request):
        # 如果是post请求,说明是用户点击添加按钮提交了表单
        if request.method == 'POST':
            # 获取表单中的值,然后添加到列表中(模拟数据库)
            user = request.POST.get('username', None)
            email = request.POST.get('email', None)
            gender = request.POST.get('gender', None)
            content = {'username': user, 'email': email, 'gender': gender}
            USER_LIST.append(content)
        # 返回home页面信息
        return render(request, 'home.html', {'user_list': USER_LIST})

    当请求是POST类型时,说明用户提交了新的用户数据,使用request获取数据,并存放到列表(模拟数据库)中。然后将列表中的全部数据作为参数交给django框架,框架对home.html进行替换后返回给浏览器。

    十三、Django框架中请求的生命周期

     一个非静态资源请求的URL,生命周期一般如上图所示:

    1.客户端发送请求给服务器(图中省略),服务器将请求交给django的路由系统(对应urls.py)

    2.路由系统判断是否存在对应的映射,如果存在,则找到并执行对应的视图方法(对应APP中的views.py中的函数或类)

    3.视图方法根据业务需求,从数据库等存储中获取业务数据,并使用指定的模板文件(对应html文件)来渲染显示效果(即使用业务数据替换html中指定部分)

    4.返回合并好的数据给客户端(浏览器)

    十四、Django基础内容总结

    1.创建Django工程:

    使用命令行:django-admin startproject pro_name

    或者使用pycharm创建

    2.创建APP

    使用命令行:python manage.py startapp app_name

    3.配置Django

    配置静态文件目录:settings.py

    最后添加:

    STATICFILES_DIRS = (
        os.path.join(BASE_DIR, 'static'),
    )

    配置模板文件目录(默认是templates):settings.py

    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',
                ],
            },
        },
    ]

    禁用CSRF认证(防止post提交403错误):settings.py

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        #'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

    4.定义路由规则

    在urls.py中添加访问URL于视图函数之间的映射关系

      例如:"login" ---> func_name

    5.定义视图函数

    在app的views.py中定义视图函数

    def func_name(request):
        if request.method == 'POST':
            data = request.POST.get('data_name', None)
            pass
        elif request.method == 'GET':
            data = request.GET.get('data_name', None)
            pass
        return render(request, 'xxx.html', {'data_key': data_value})

    返回字符串:

    return HttpResponse("字符串")

    返回模板:

    return render(request,'xxx.html',{替换数据字典})

    重定向:

    return redirect('/login')  # 这里的"/"表示本地,即httP://127.0.0.1/
    return redirect('http://www.baidu.com') # 外部url

    十五、模板渲染(模板语言)

    在Django中存在一套特殊的模板语言:

    在settings.py中可以看到:

    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',
                ],
            },
        },
    ]

    Django提供的默认模板语言叫做DjangoTemplates,这套模板语言可能存在一些局限性,我们可以将其修改为Jinjia2模板语言:

    'BACKEND': 'django.template.backends.jinja2.Jinja2',

    但是在这里,我们还是先学习默认的模板语言*(^。^)**。以下都是默认模板语言,Jinjia2以后再学习。

    在使用render返回数据时,Django会将数据和模板合并

    return render(request, 'index.html', {'current_user': 'Leo',
                                          'user_list': ['Alex', 'Eric', 'Jone', 'Leo'],
                                          'user_dict': {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'},
                                          'age': 18
                                          })

    在index.html中使用{{ username }}就可以获取到user的值,并自动替换在相应的位置:

    <div>{{ username }}</div>

    替换后变为:

    <div>Leo</div>

    index.html中使用循环获取user_list中的值:

        <ul>
            {% for row in user_list %}
                <li>{{ row }}</li>
            {% endfor %}
        </ul>

    获取列表中的某个值:

    <div>{{ user_list.2 }}</div>  <!-- 获取user_list中的第2个值 -->
    <div>{{ user_list.3 }}</div>  <!-- 获取user_list中的第3个值 -->

    index.html中循环获取user_dict中的值:

    <!-- 获取所有key -->
    <ul>
        {% for row in user_dict.keys %}
            <li>{{ row }}</li>
        {% endfor %}
    </ul>
    <!-- 获取所有value -->
    <ul>
        {% for row in user_dict.values %}
            <li>{{ row }}</li>
        {% endfor %}
    </ul>
    <!-- 获取所有key和value -->
    <ul>
        {% for key,value in user_dict.items %}
            <li>{{ key }} <---> {{ value }}</li>
        {% endfor %}
    </ul>

    通过key获取字典中的值:

    <div>{{ user_dict.k1 }}</div>  <!-- 获取字典中键为k1对应的值-->
    <div>{{ user_dict.k2 }}</div>  <!-- 获取字典中键为k2对应的值-->

    循环计数:

    如果想在循环中打印循环的次数(count),可以使用以下方式:

    <ul>
        {% for row in user_list %}
            <li>{{ forloop.counter }}</li>  <!-- 从1开始计数 -->
            <li>{{ forloop.counter0 }}</li>  <!-- 从0开始计数 -->
            <li>{{ forloop.revcounter }}</li>  <!-- 1开始计数,但是反向排列 -->
            <li>{{ forloop.revcounter0 }}</li>  <!-- 0开始计数,但是反向排列 -->
            <li>{{ forloop.first }}</li>  <!-- 第一次循环为True,后面全为False -->
            <li>{{ forloop.last }}</li>  <!-- 第一次循环为False,后面全为True -->
        {% endfor %}
    </ul>

    如果是多层循环:

    <ul>
        {% for outer in user_list %}
            {% for row in user_list %}
                <li>{{ forloop.parentloop }}</li>  <!-- 外层循环的6个属性,以字组织 -->
                <li>{{ forloop.parentloop.counter }}</li>  <!-- 获取外层循环的次数(1开始计数) -->
            {% endfor %}
        {% endfor %}
    </ul>

    if判断语句:

    {% if age %}
        <a>有年龄信息</a>
        {% if age > 16 %}
            <a>老男人</a>
        {% else %}
            <a>小鲜肉</a>
        {% endif %}
    {% else %}
        <a>没有年龄信息</a>
    {% endif %}
  • 相关阅读:
    MySQL基准测试--innodb_buffer_pool_instances
    MySQL参数优化:back_log
    MySQL open_files_limit相关设置
    Django权限系统auth模块详解
    2.9 go mod 之本地仓库搭建
    my40_MySQL锁概述之意向锁
    my39_InnoDB锁机制之Gap Lock、Next-Key Lock、Record Lock解析
    2.8 GO 参数传递
    my38_MySQL事务知识点零记
    my37_MGR流控对数据库性能的影响以及MGR与主从的性能对比
  • 原文地址:https://www.cnblogs.com/leokale-zz/p/12043610.html
Copyright © 2020-2023  润新知