django關於URL、Template、Model的一些高級應用

URL配置的一些技巧:html

一、添加視圖前綴的方法:node

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

二、使用命名參數:python

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

視圖進行以下匹配:web

month_archive(request, year='2006', month='03')正則表達式

使用命名參數順序以下:django

  • 若是包含命名參數,則忽略全部未命名參數
  • 若是沒有,則使用順序參數調用
  • 以上兩種方式中,均可以傳遞額外選項。

三、生成通用視圖app

# 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})

現重構以下:ide

# 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})

四、匹配特例

在經過正則表達式處理大量url請求時,可能須要對某個特定的url請求調用不一樣的視圖處理函數。解決的方法是將須要匹配的url特例放在通用的正則表達式前,以下例:函數

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

五、包含其餘URLui

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不要以$結尾!!!

六、傳遞額外參數

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
相關文章
相關標籤/搜索