Django基础篇

Posted 摘星者的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django基础篇相关的知识,希望对你有一定的参考价值。

一、视图和路由系统

    如果大家曾经发布过Hello,world页面,但是没有使用Web框架,只是简单的在hello.html文本中输入hello,world,然后上传到任意的一个网页服务器上。注意,这个过程中,说明了两个关于网页的关键信息:它包括(字符串"hello,world")和它的URL(http://www.example.com/hello.html)。

    使用Django来完成上面的步骤,需要用的知识:页面的内容是靠view function(视图函数)来产生,URL定义在URLconf中。下面,我们来通过Django来实现一个Hello,world的页面。

1,视图

    我们在创建项目的时候在mysite文件夹中,生成了一个名为views.py的文件,我们的Hello,World视图非常简单,这些是完整的函数和导入声明,代码如下:

1
2
3
4
form django.http import HttpResponse
 
def hello(request):
    return HttpResponse("Hello,World")

    首先我们需要导入HttpResponse模块,因为在Django在返回数据的时候需要一层封装,接下来,我们定义一个叫做hello的视图函数,每个视图函数至少有一个参数,通常被叫做request。这是一个触发这个视图、包含当前Web请求信息的对象,是类django.http.HttpRequest的一个实例。我们定义完了视图后,就需要让Django找到我们定义的这个视图函数。

2、路由系统

    现在,如果我们运行:python mangage.py runserver,还是看到的Django的欢迎界面,而看不到我们刚才写的Hello World显示页面。这是因为我们的mysite项目还对hello视图一无所知。我们需要通过一个详细描述的URL来显示告诉它并且激活这个视图,这里我们就用到了我们的路由系统。

    urls.py是我们在创建cmdb时生成的,这个文件就像是Django所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表。

1
2
3
4
5
6
7
8
from django.conf.urls import url
from django.contrib import admin
from cmdb import views
 
urlpatterns = [
    # url(r\'^admin/\', admin.site.urls),
    url(r\'^hello/\', views.hello),
]

    这里有一个问题值得声明一下,Django在检查URL模式前,移除每一个申请的URL开头的斜杠,这意味着我们为/hello/写URL模式不用包含斜杠,URL的模式包含了一个尖角号(^)和一个美元符号($),这些都是正则表达式符号,并且有特定的含义:上尖角要求表达式对字符串的头部进行匹配,美元符号则要求表达式对字符串的尾部进行匹配。

    如果你是喜欢所有URL都以\'/\'结尾的话,那么只需要在每个URL后添加斜杠,并且设置settings里的"APPEND_SLASH"为"True";如果不喜欢URL以斜杠结尾或者根据每个URL来决定,那么需要设置"APPEND_SLASH"为"False",并且根据你自己的意愿来添加结尾斜杠在URL模式后。

刚才我们也提到了在路由系统中可以使用正则表达式来进行匹配,下面我们就来举几个应用正则表达式的例子:

例一:每个路由规则对应一个view中的函数

1
2
3
4
5
6
7
8
9
10
url(r\'^index/(\\d*)\',views.index),
#匹配index/后面带数字的页面,如:index/1/,index/2/
  
 
url(r\'^manage/(?P<name>\\w*)/(?P<id>\\d*)\',views.manage),
#匹配manage/所有字符赋值给name/所有数字赋值给id,这是正则表达式的分组
  
 
url(r\'^manage/(?P<id>\\d+/$)\',views.manage,{\'id\':333}),
#这里,正则表达式和额外字典都包含了一个id。额外字典的id将优先使用,就是说任何请求都会作id设置为333对待,不管URl里面捕捉到什么样的值。
 

同时也要修改views的配置:

1
2
3
4
5
6
7
8
9
10
def login(request):    
    return HttpResponse(\'Ok\')
 
def detail(request,nid):
    print(nid)
    return HttpResponse(\'Ok\')
 
def detail2(request,nid,nnid):
    print(nid,nnid)
    return HttpResponse(\'Ok\')

例二:根据app对路由规则进行一次分类

1
2
3
url(r\'^web/\',include(\'web.urls\')),
 
#每当Django遇到include()时,不再是当前的url来处理了,而是将请求发送到web app里自定义的urls进行处理(路由分发)。

    Dajngo中的路由系统和其他语言的框架有所不同,在Django中每一个请求的URL都要有一条路由映射,这样才能将请求交给一个views中的函数去处理。其他大部分的Web框架则是一类的url请求做一条路由映射,从而使路由系统变得简洁,如果想让页面跳转到自定义页面return redirect(自定义界面)

例三:利用反射机制,为Django开发一套动态路由系统

配置urls.py路由映射:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from django.conf.urls import patterns, include, url
from django.contrib import admin
from DynamicRouter.activator import process
 
urlpatterns = patterns(\'\',
    # Examples:
    # url(r\'^$\', \'DynamicRouter.views.home\', name=\'home\'),
    # url(r\'^blog/\', include(\'blog.urls\')),
 
    url(r\'^admin/\', include(admin.site.urls)),
     
     
    (\'^(?P<app>(\\w+))/(?P<function>(\\w+))/(?P<page>(\\d+))/(?P<id>(\\d+))/$\',process),
    (\'^(?P<app>(\\w+))/(?P<function>(\\w+))/(?P<id>(\\d+))/$\',process),
    (\'^(?P<app>(\\w+))/(?P<function>(\\w+))/$\',process),
    (\'^(?P<app>(\\w+))/$\',process,{\'function\':\'index\'}),
)

根据urls.py中获取的参数,通过反射调用指定app/views.py中的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/env python
#coding:utf-8
 
from django.shortcuts import render_to_response,HttpResponse,redirect
 
 
def process(request,**kwargs):
    \'\'\'接收所有匹配url的请求,根据请求url中的参数,通过反射动态指定view中的方法\'\'\'
     
    app =  kwargs.get(\'app\',None)
    function = kwargs.get(\'function\',None)
     
    try:
        appObj = __import__("%s.views" %app)
        viewObj = getattr(appObj, \'views\')
        funcObj = getattr(viewObj, function)
         
        #执行view.py中的函数,并获取其返回值
        result = funcObj(request,kwargs)
         
    except (ImportError,AttributeError),e:
        #导入失败时,自定义404错误
        return HttpResponse(\'404 Not Found\')
    except Exception,e:
        #代码执行异常时,自动跳转到指定页面
        return redirect(\'/app01/index/\')
     
    return result

执行方法:

1
2
3
4
5
http://127.0.0.1:9000/app01/index/  ==》 执行app01/view.py文件中的index函数
 
http://127.0.0.1:9000/app02/index/  ==》 执行app02/view.py文件中的index函数
 
http://127.0.0.1:9000/app01/login/  ==》 执行app01/view.py文件中的login函数

例四:实现网页分页显示

urls.py配置:

1
2
3
4
5
6
from django.conf.urls import url
from django.contrib import admin
from app01 import views
 
urlpatterns = [
    url(r\'^index/(\\d+)\', views.index),

views.py配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from django.shortcuts import render
  
from django.shortcuts import HttpResponse
  
USER_LIST = []         #制造一些数据
for item in range(94):
    temp = {\'id\':item,\'user\':\'haifeng\' + str(item),\'email\':\'email\' + str(item)}
    USER_LIST.append(temp)
  
def index(request,page):
    """
  
    :param request:
    :param page:进行数据分页显示
    :return:
    """
    page = int(page)
    start = (page - 1) * 10
    end = page * 10
    user_list = USER_LIST[start:end]
    return render(request,\'index.html\',{\'user_list\':user_list})

访问效果:

例五:根据用户输入的ID号查找出ID详细信息

urls.py配置:

1
2
3
4
5
6
7
from django.conf.urls import url
from django.contrib import admin
from app01 import views
 
urlpatterns = [
    url(r\'^admin/\', admin.site.urls),
    url(r\'^detail/(\\d+)\', views.detail),

views.py配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from django.shortcuts import render
 
# Create your views here.
 
from django.shortcuts import HttpResponse
 
USER_LIST = []
for item in range(94):
    temp = {\'id\':item,\'user\':\'haifeng\' + str(item),\'email\':\'email\' + str(item)}
    USER_LIST.append(temp)
 
def detail(request,nid):
    """
 
    :param request:
    :param nid:根据数据的ID查找出对应ID的所有信息
    :return:
    """
    nid = int(nid)
    current_detail_dict = USER_LIST[nid]
    return render(request,\'detail.html\',{\'current_detail_dict\':current_detail_dict})

detail.html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>detail</title>
</head>
<body>
    <ul>
        <li>
            {{ current_detail_dict.id }}
        </li>
        <li>
            {{ current_detail_dict.user }}
        </li>
        <li>
            {{ current_detail_dict.email }}
        </li>
    </ul>
 
</body>
</html>

访问效果:

二、模板

    模板是一个文本,用于分离文档的表现形式和内容。模板定义了占位符以及各种用语言规范文档该如何显示的各部分基本逻辑(模板标签)。模板通常用于产生HTML,但是Django的模板也能产生任何基于文本格式的文档。

1、模板语言

模板中也有自己的语言,该语言可以实现数据展示,下面我们根据这个views.py来具体介绍一下模板语言:

1
2
3
4
5
6
7
8
9
def template(request):
    """
    自定义方法,filter,simple_tag
    :param request:
    :return:
    """
    return render(request,
                  \'template.html\',
                  {\'k1\':\'vvv\',\'k2\':[11,22,33],\'k3\':{\'nid\':12,\'name\':\'jack\'}})
  • {{ k1 }}:定义变量,结果:vvv;

  • {{ k1.0 }}:索引位置为0的字符,结果:v;

  • {{ k1.name }}:获取字典里name的值,结果:jack;

  • for循环

1
2
3
4
5
6
7
8
9
10
11
{% for item in k2 %}        #循环k2这个列表
    <p>{{ item }}</p>       #获取所有值,11,22,33
 
    <p>{{ forloop.counter }}</p>       #获取索引位置,但这个索引位置从1开始
    <p>{{ forloop.counter0 }}</p>      #获取索引位置,但将初始索引位置至为0
 
    <p>{{ forloop.first }},{{ forloop.last }}</p> #判断是否是第一个或最后一个,返回结果为:True or False
 
    <p>{{ forloop.revcounter }}</p>    #倒排索引,从1开始
 
{% endfor }
  • {% if ordered_warranty %},{% else %},{ % endif % }

  • 母板:{% block title %},{% endblock %}

  • 子板:{% extends "base.html" %},{% block title %},{% endblock %}

例:模板继承,减少公用页面区域所引起的重复和冗余代码

urls.py定义路由规则:

1
2
3
4
5
6
7
8
from django.conf.urls import url

(c)2006-2024 SYSTEM All Rights Reserved IT常识