django关于URL、Template、Model的一些高级应用

URL配置的一些技巧:

1、添加视图前缀的方法:

from django.conf.urls.defaults import *
 
urlpatterns = patterns('mysite.views',
    (r'^hello/$', 'hello'),
    (r'^time/$', 'current_datetime'),
    (r'^time/plus/(d{1,2})/$', 'hours_ahead'),
)

2、使用命名参数:

from django.conf.urls.defaults import *
from mysite import views
 
urlpatterns = patterns('',
    (r'^articles/(?P<year>\d{4})/$', views.year_archive),
    (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', views.month_archive),
)

视图进行如下匹配:

month_archive(request, year='2006', month='03')

使用命名参数顺序如下:

  • 如果包含命名参数,则忽略所有未命名参数
  • 如果没有,则使用顺序参数调用
  • 以上两种方式中,都可以传递额外选项。

3、生成通用视图

# urls.py
 
from django.conf.urls.defaults import *
from mysite import views
 
urlpatterns = patterns('',
    (r'^events/$', views.event_list),
    (r'^blog/entries/$', views.entry_list),
)
 
# views.py
 
from django.shortcuts import render_to_response
from mysite.models import Event, BlogEntry
 
def event_list(request):
    obj_list = Event.objects.all()
    return render_to_response('mysite/event_list.html', {'event_list': obj_list})
 
def entry_list(request):
    obj_list = BlogEntry.objects.all()
    return render_to_response('mysite/blogentry_list.html', {'entry_list': obj_list})

现重构如下:

# urls.py
 
from django.conf.urls.defaults import *
from mysite import models, views
 
urlpatterns = patterns('',
    (r'^events/$', views.object_list, {'model': models.Event}),
    (r'^blog/entries/$', views.object_list, {'model': models.BlogEntry}),
)
 
# views.py
 
from django.shortcuts import render_to_response
 
def object_list(request, model):
    obj_list = model.objects.all()
    template_name = 'mysite/%s_list.html' % model.__name__.lower()
    return render_to_response(template_name, {'object_list': obj_list})

4、匹配特例

在通过正则表达式处理大量url请求时,可能需要对某个特定的url请求调用不同的视图处理函数。解决的方法是将需要匹配的url特例放在通用的正则表达式前,如下例:

urlpatterns = patterns('',
    # ...
    ('^auth/user/add/$', views.user_add_stage),
    ('^([^/]+)/([^/]+)/add/$', views.add_stage),
    # ...
)

5、包含其他URL

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'),
)

注意:包含的URL不要以$结尾!!!

6、传递额外参数

from django.conf.urls.defaults import *
 
urlpatterns = patterns('',
    (r'^blog/', include('inner'), {'blogid': 3}),
)
 
# inner.py
 
from django.conf.urls.defaults import *
 
urlpatterns = patterns('',
    (r'^archive/$', 'mysite.views.archive'),
    (r'^about/$', 'mysite.views.about'),
    (r'^rss/$', 'mysite.views.rss'),
)

模板的高级技巧:

RequestContext类和Context处理器

下面通过一个例子来看一下RequestContext的使用。

from django.template import loader, Context
 
def view_1(request):
    # ...
    t = loader.get_template('template1.html')
    c = Context({
        'app': 'My app',
        'user': request.user,
        'ip_address': request.META['REMOTE_ADDR'],
        'message': 'I am view 1.'
    })
    return t.render(c)
 
def view_2(request):
    # ...
    t = loader.get_template('template2.html')
    c = Context({
        'app': 'My app',
        'user': request.user,
        'ip_address': request.META['REMOTE_ADDR'],
        'message': 'I am the second view.'
    })
    return t.render(c)

通过使用RequestContext,就可以简化上面的代码:

from django.template import loader, RequestContext
 
def custom_proc(request):
    "A context processor that provides 'app', 'user' and 'ip_address'."
    return {
        'app': 'My app',
        'user': request.user,
        'ip_address': request.META['REMOTE_ADDR']
    }
 
def view_1(request):
    # ...
    t = loader.get_template('template1.html')
    c = RequestContext(request, {'message': 'I am view 1.'},
            processors=[custom_proc])
    return t.render(c)
 
def view_2(request):
    # ...
    t = loader.get_template('template2.html')
    c = RequestContext(request, {'message': 'I am the second view.'},
            processors=[custom_proc])
    return t.render(c)

对于render_to_response()函数,我们可以使用context_instance参数:

from django.shortcuts import render_to_response
from django.template import RequestContext
 
def custom_proc(request):
    "A context processor that provides 'app', 'user' and 'ip_address'."
    return {
        'app': 'My app',
        'user': request.user,
        'ip_address': request.META['REMOTE_ADDR']
    }
 
def view_1(request):
    # ...
    return render_to_response('template1.html',
        {'message': 'I am view 1.'},
        context_instance=RequestContext(request, processors=[custom_proc]))
 
def view_2(request):
    # ...
    return render_to_response('template2.html',
        {'message': 'I am the second view.'},
        context_instance=RequestContext(request, processors=[custom_proc]))

定制模板过滤器

过滤器函数可以有一个或两个参数,第一个参数为输入,第二个参数为选项。下面来看一些例子:

def cut(value, arg):
    "Removes all values of arg from the given string"     return value.replace(arg, '')
{{ somevariable|cut:" " }}
def lower(value): # Only one argument.     "Converts a string into all lowercase"     return value.lower()

注册定制过滤器的代码如下:

from django import template
 
register = template.Library() register.filter('cut', cut) register.filter('lower', lower)
定制模板标签

在django中,模板系统的工作分为两部分:编译和渲染。

在编译的过程中,django会分析模板标签,并将其生成相应的django.template.Node对象,该对象中包含有render()函数。可参考下面的例子:

Hello, {{ person.name }}.
 
{% ifequal name.birthday today %}
    Happy birthday!
{% else %}
    Be sure to come back on your birthday
    for a splendid surprise message.
{% endifequal %}

上面的模板在分析后,会生成如下Node列表:

  • Text node: "Hello, "
  • Variable node: person.name
  • Text node: ".\n\n"
  • IfEqual node: name.birthday and today

在编译完成后,会依次调用每个Node的render()函数进行渲染。

编译函数的编写

下面通过一个{% current_time %}标记来演示定制标签的方法。我们要实现的标签的使用方法如下:

<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>

首先是编译函数:

from django import template
 
register = template.Library()  def do_current_time(parser, token):
    try:
        # split_contents() knows not to split quoted strings.         tag_name, format_string = token.split_contents()     except ValueError:
        msg = '%r tag requires a single argument' % token.split_contents()[0]         raise template.TemplateSyntaxError(msg)     return CurrentTimeNode(format_string[1:-1])

需要注意的是,在编译函数中不能抛出异常。返回的一定是一个Node的子类。

创建Node子类

下面来创建CurrentTimeNode类:

import datetime
 
class CurrentTimeNode(template.Node):
    def __init__(self, format_string):
        self.format_string = str(format_string)
 
    def render(self, context):
        now = datetime.datetime.now()
        return now.strftime(self.format_string)
注册标签

注册标签的方法如下:

register.tag('current_time', do_current_time)


模型的高级应用

添加额外的管理器

# models.py
 
from django.db import models
 
# ... Author and Publisher models here ...
 
class BookManager(models.Manager):
    def title_count(self, keyword):
        return self.filter(title__icontains=keyword).count()
 
class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()
    num_pages = models.IntegerField(blank=True, null=True)
    objects = BookManager()
 
    def __unicode__(self):
        return self.title

使用如下:

>>> Book.objects.title_count('django')
4
>>> Book.objects.title_count('python')
18

转载于:https://my.oschina.net/u/267204/blog/68120

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值