DJango views用法

URLconf技巧
因为urls.py也是一个python文件,所以你可以在这个文件中使用python允许的任何语法。
先看之前介绍的例子:
from django.conf.urls  import patterns, include, url
from books.views  import hello, search_form,  search, contact, thanks

urlpatterns  = patterns( '',
    url(r '^hello/$', hello),
    url(r '^search/$'search),
    url(r '^contact/$', contact),
    url(r '^contact/thanks/$', thanks),
)
每一个路径匹配需要导入相应的模块,所以当app的规范越来越大的时候,第二行的import语句
就越长。。。所以可以采用以下几种方法来必定:
1. 只import到模块就可以了,不用写出函数
from django.conf.urls  import patterns, include, url
from books  import views
urlpatterns  = patterns( '',
    url(r '^hello/$', views.hello),
    url(r '^search/$', views. search),
    url(r '^contact/$', views.contact),
    url(r '^contact/thanks/$', views.thanks),
)
2. 使用字符串来代表需要执行的views函数,这里就需要写全路径
from django.conf.urls  import patterns, include, url

urlpatterns  = patterns( '',
    url(r '^hello/$''books.views.hello'),
    url(r '^search/$''books.views.search'),
    url(r '^contact/$', 'books.views.contact'),
    url(r '^contact/thanks/$''books.views.thanks'),
)
3. 更简单的字符串写法,需要使用到patterns()的第一个参数
from django.conf.urls  import patterns, include, url

urlpatterns  = patterns( 'books.views',
    url(r '^hello/$''hello'),
    url(r '^search/$''search'),
    url(r '^contact/$', 'contact'),
    url(r '^contact/thanks/$''    thanks'),
)
以上的方法都是合法的,具体看你选择了。
 
因为patterns()返回的对象可以进行加法,当遇到多个views模块的路径前缀时,可以使用如下方式
来统一管理你的路径匹配:
from django.conf.urls  import patterns, include, url

urlpatterns  = patterns( 'books.views',
    url(r '^hello/$''hello'),
    url(r '^search/$''search'),
    url(r '^contact/$', 'contact'),
    url(r '^contact/thanks/$''    thanks'),
)

urlpatterns  += patterns( 'weblogs.views',
    url(r '^hello/$''world'),
)
使用正规表达式的组操作来向views传递参数
正则表达式可以使用()来表示匹配成功的组,同时可以使用后向引用\1,\2...\n来表示不同的组,
在表达式中代表重复的匹配字串。
不用groups的话,返回的一个match对象。
 
在python中还可以为组命名,使用(?P<year>\d{4}),意思是这个组的名字为year,匹配的是4个数字
正因为有命名组和不命名组的这两种使用,正好可以以两种方式给view函数传递参数:
1. 不命名组以顺序的方式传值
# views.py
def count( self, a, b) :
    ....
#urls.py
(r '^num/(\d{4})/(\d{2})/$', count),
#结果
#对于请求/num/1234/78,产生的调用为count(1234, 78)
2. 命名组以字典的方式传值
#urls.py
(r '^num/(?P<b>\d{4})/(?P<a>\d{2})/$', count),
#结果
#对于请求/num/1234/78,产生的调用为count(b=1234, a=78)
通过比较,使用命名组有更大的优势,可以让代码一目了然,也不用担心参数的顺序搞错。
还是最好不用混用命名组和非命名组,虽然Django不会报错,但不太好,你懂的。
 
下面了解一下url匹配的过程:
1. 如果含有命名组,优先采用字典参数
2. 其余的非命名组将会以顺序的方式传递到剩余的参数中
3. url中其它的选项,将会以字典的方式传递
#urls.py
urlpatterns  = patterns( '',
     #第三个选项值可用来传递一些附加信息,同时可以让请求路径简洁一点
     #否则有时候请求链接带太多参数也不太好
    (r '^foo/(?P<a>\d{2})$', count, { 'b' :  43}),
)
#结果
#对于请求/num/12,产生的调用为count(12, b=43)
当然,view的函数可以使用默认值,这样,如果请求路径中没有匹配到值的话,会调用默认的值。
注意,一般来说默认值应该设置为字符串,这样是和请求路径匹配过来的值的类型保持一致。因为
它们都是字符串。 即使你匹配的是数学,传入的还是数字的字符串,需要使用int()函数进行转化成
真正的整数。
 
在这里复习一下,django到底会匹配请求路径的哪一部分?
1. 给定请求路径www.example.com/myapp/foo
只会匹配myapp/foo这个部分
 
2. 给定请求路径www.example.com/myapp/foo?name=david
只会匹配myapp/foo这个部分
 
3. 给定请求路径www.example.com/myapp/foo#name=david
只会匹配myapp/foo这个部分
 
请求路径中也不会包含请求GET还是POST,任何匹配成功的请求,都会运行同一个函数,
但这样做不太好,最好还是对GET和POST采用不同的处理,这里就要用到request对象,
之前也介绍过,它包含了丰富的信息。
def foo(request) :
     if request.method  ==  'POST' :
         #handle post ...
         #need to redirect
         return HttpResponseRedirect( '/someurl/')
     elif request.method  ==  'GET' :
         #handle get
         #just return response
         return render_to_response( 'page.html')
通过路径匹配动态构造view中的函数
上代码:
#views.py
def say_hello( self, person_name) :
     print  'Hello, %s'  % person_name

def say_goodbye( self, person_name) :
     print  'Goodbye, %s'  % person_name
#urls.py
urlpatterns  = patterns( '',
    (r '^say_hello/(\w+)$', say_hello),
    (r '^say_goodbye/(\w+)/$', say_goodbye),
)
上面两个函数基本是做同一件事,传入一个人的名字,然后问候一句。
所以稍微改动一下匹配规则,创建一个动态处理这两件事的一个函数。
#views.py
def greet( self, person_name, greeting) :
     print  '%s, %s'  % person_name

#urls.py
urlpatterns  = patterns( '',
    (r '^say_hello/(\w+)$', greet, { 'greeting' : 'Hello'}),
    (r '^say_goodbye/(\w+)/$', greet, { 'greeing' : 'Goodbye'}),
)
可以看到url中的第三个选项值可以传入额外的信息,保持请求路径的简洁。
同时,这个选项值还可以传入model类,使用委托的方式,让你的view函数功能更加动态。
还可以传入模块名称,让你不用把模块名写死在render_to_response函数中。
 
还有一点需要注意,当命名组的名字和第三个选项值的名字相同时,Django会使用第三个选项值,
因为它的优先级更高。
使用闭包和可变长度参数来重构views函数
这里要用的概念有:
1. 函数对象也可以当参数进行传递
2. 闭包,可以简单的理解为是函数中定义函数
3. 参数中*args代表可变长度元组参数,也叫非关键字参数,**args代表可变长度字典类参数,也叫关键字参数
注意报错内容,关键字参数一定要放在最右边
 
重构例子:
def my_view1(request) :
     if  not request.user.is_authenticated() :
         return HttpResponseRedirect( '/accounts/login/')
     # ...
     return render_to_response( 'template1.html')

def my_view2(request) :
     if  not request.user.is_authenticated() :
         return HttpResponseRedirect( '/accounts/login/')
     # ...
     return render_to_response( 'template2.html')

def my_view3(request) :
     if  not request.user.is_authenticated() :
         return HttpResponseRedirect( '/accounts/login/')
     # ...
     return render_to_response( 'template3.html')
#这上面三个方法,一开始都要进行验证,这有点重复
#下面添加一个新的方法
def requires_login(view) :
     def new_view(request,  *args,  **kwargs) :
         if  not request.user.is_authenticated() :
             return HttpResponseRedirect( '/accounts/login/')
         return view(request,  *args,  **kwargs)
     return new_view
#使用闭包,定义相同的验证的部分,并返回相应的函数对象,这样就可以
#在上面三个函数中实现自己不同的代码了。可以把验证的部分统统去掉。
#另外urls.py可以改成
from django.conf.urls.defaults  import  *
from mysite.views  import requires_login, my_view1, my_view2, my_view3

urlpatterns  = patterns( '',
    (r '^view1/$', requires_login(my_view1)),
    (r '^view2/$', requires_login(my_view2)),
    (r '^view3/$', requires_login(my_view3)),
)
使用include()引用其它路径配置文件
from django.conf.urls.defaults  import  *

urlpatterns  = patterns( '',
    (r '^weblog/', include( 'mysite.blog.urls')),
    (r '^photos/', include( 'mysite.photos.urls')),
    (r '^about/$''mysite.views.about'),
)
一个project有一个总的urls.py,各个app也可以自己建立自己的urls.py,不过都需要使用include()
函数在project的urls.py文件进行注册。这样利用你的项目管理。
 
可以注意到使用了include的路径的匹配表达式没有加上'$',这是因为Django的机制是
把当前匹配的请求路径的部分去除,剩下的部分传到include所指定的路径配置中进行匹配。
比如一个请求路径/weblog/7000/过来,匹配部分是weblog/7000/,又因为weblog/匹配成功,
就把剩余的部分7000/传入到mysit.blog.urls文件中进行下一步的匹配。
 
当使用include()的路径匹配中含有正则组的时候,这个匹配的参数会传入对include中所指定的urlconf中
所有的函数里,不管函数是接受这个参数,显然很容易报错,所以这种做法不太好。
 
同理,如果你在include的路径匹配中使用了第三个选项参数,也会强制传入指定的urlconf中的所有函数中。
也不太好。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Djangoviews函数可以调用其他函数。这些函数可以是在views.py文件定义的,也可以是在其他文件定义的。调用函数的方法与普通的Python函数调用相同。例如,可以使用以下代码在views函数调用另一个函数: ``` def my_view(request): # 调用另一个函数 result = my_function() # 处理结果并返回响应 ... def my_function(): # 执行一些操作并返回结果 ... ``` 在这个例子,my_view函数调用了my_function函数,并使用返回的结果进行处理。注意,如果调用的函数在另一个文件定义,需要使用import语句导入该文件。 ### 回答2: Django 是一个使用 Python 语言编写的 Web 框架,它主要用于快速构建高性能的 Web 应用程序。Django 的视图函数通常包括两大部分:请求处理和响应生成。在大多数情况下,视图函数只负责处理单一的请求,因此很少需要调用其他的视图函数。但在某些特定的场景下,一个视图函数需要调用另一个视图函数,这时候就要用到 Django 的函数调用函数。 Django 的函数调用函数实际上就是将一个函数作为参数传递给另一个函数,从而实现不同视图函数间的调用。在 Django ,这种方式非常常见,尤其是在类视图使用较多。具体实现方式如下: 1. 在 views.py 定义第一个视图函数。 ``` def first_view(request): # 处理请求的具体逻辑 second_view(request) return HttpResponse("Hello, World!") ``` 2. 在 views.py 定义第二个视图函数。 ``` def second_view(request): # 处理请求的具体逻辑 return HttpResponse("This is the second view.") ``` 3. 在第一个视图函数 first_view 通过函数调用函数的方式调用第二个视图函数 second_view。 4. 最后返回一个 HttpResponse 对象。 需要注意的是,这种方式并不是特别推荐,因为它可能会导致代码的复杂性增加,特别是在视图需要调用多个其他视图的时候。此外,如果视图之间存在相互依赖的情况,建议将其抽象成一个公共类或函数实现,以便统一管理和调用。 ### 回答3: 在Django,view函数是处理浏览器请求的函数。当用户请求URL时,view函数接收该请求并生成所需的HTML响应。在某些情况下,您可能想要从一个视图函数调用另一个视图函数。在这种情况下,您可以使用Django的导入和函数调用机制来实现。 首先,在你的views.py文件定义所有的视图函数,然后在你的urls.py文件将它们与特定的URL绑定。这将使您可以在浏览器上访问视图函数。现在,如果你想从一个视图函数调用另一个视图函数,你可以简单地导入另一个视图函数并使用它。 例如,假设你有一个视图函数A和另一个视图函数B。现在,当用户访问视图函数A时,您想让它调用视图函数B并返回其响应。为此,您需要导入B函数并将其调用。 ``` from . import views // 从同一个app导入views模块 def A(request): response1 = HttpResponse("This is View A") response1 += views.B(request) // 访问B的响应 return response1 def B(request): response2 = HttpResponse("This is View B") return response2 ``` 在上面的代码,当用户访问视图函数A时,该函数会生成一个与该函数相关的响应。然后,在视图函数A,您导入视图函数B并使用它。您使用上述方法将B视图的返回值添加到A视图的响应,并最终返回完整的响应。 这是一个简单的例子,您可以使用类似的模式从一个视图函数调用其他视图函数。从一个视图函数调用另一个视图函数是Django的常见模式,并且非常有用。如果您正处于这种情况下,请使用上面的步骤来完成它。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值