为了让项目更好维护,应当尽量减少硬编码,使用permalink能减少url硬编码。我们直接看下它的源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
def permalink(func):
"""
Decorator that calls urlresolvers.reverse() to return a URL using
parameters returned by the decorated function "func".
"func" should be a function that returns a tuple in one of the
following formats:
(viewname, viewargs)
(viewname, viewargs, viewkwargs)
"""
from django.core.urlresolvers import reverse
@wraps(func)
def inner(*args, **kwargs):
bits = func(*args, **kwargs)
return reverse(bits[0], None, *bits[1:3])
return inner
|
由此不难看出,permalink实质是一个装饰器。
其实在我之前的yunfan项目中就用了permalink,主要是受‘django-basic-apps’的启发,很认真地看过这个项目的源码,感觉写得挺好看的。带领大家弄懂permalink的原理后,我们再来看看permalink在django-basic-apps的groups模块中的应用,如此一来将理论与实践结合。
好,废话不说,关于permalink,先看django官网解释:
-
This decorator takes the name of a URL pattern (either a view name or a URL pattern name) and a list of position or keyword arguments and uses the URLconf patterns to construct the correct, full URL. It returns a string for the correct URL, with all parameters substituted in the correct positions.
balabala说了一堆,我们还是直接看例子吧:
1
2
3
4
5
6
7
8
9
10
11
|
#urls.py
(r'^people/(\d+)/$', 'people.views.details'),
#models.py
from django.db import models
@models.permalink
def get_absolute_url(self):
return ('people.views.details', [str(self.id)])
#get_absolute_url一般是某个类的方法
|
当你的url更复杂时,你会更感激permalink,像这样
1
|
(r'/archive/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/$', archive_view)
|
这是很常见的博客的url.
对应的model
1
2
3
4
5
6
|
@models.permalink
def get_absolute_url(self):
return ('archive_view', (), {
'year': self.created.year,
'month': self.created.strftime('%m'),
'day': self.created.strftime('%d')})
|
到这里其实已经很明了了。archive_view是url函数,permalink会根据archive_view指向的模式以及提供的参数字典反向解析
出url,并且返回,至此,一切搞定。
如此一来,抽象地看,对象的url似乎是对象的方法,维护起来十分方便。
在模板里只要酱紫用就行:
1
|
{% archive.get_absolute_url %}
|
多么清晰不是~
好的,我们继续看下permalink在django-basic-apps的groups模块中的应用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#urls.py
GROUP_URL = r'(?P<slug>[-\w]+)/'
urlpatterns = patterns('basic.groups.views.groups',
....
url(r'^%s$' % GROUP_URL, 'group_detail', name='group'),
)
#models.py
class Group(models.Model):
""" Group model """
title = models.CharField(blank=False, max_length=255)
slug = models.SlugField(unique=True, help_text="Used for the Group URL: http://example.com/groups/the-club/")
....
@permalink
def get_absolute_url(self):
return ('groups:group', None, {'slug': self.slug})
#group_list.html
<li><a href="{{ group.get_absolute_url }}">{{ group }}</a></li>
|
良好的代码便是最好的注释,相信大家不须我解释都看懂啦~