受到“Hidden features of…”问题系列的启发,我很想听听您所知道的Django技巧或较少人知但实用的功能。
- 每个答案请仅包含一个技巧。
- 如果有要求,请注明Django版本。
受到“Hidden features of…”问题系列的启发,我很想听听您所知道的Django技巧或较少人知但实用的功能。
我先给大家提供一个小技巧:)
在settings.py文件中使用os.path.dirname()来避免硬编码的目录名。
如果你想在不同的位置运行项目,就不要在settings.py中硬编码路径。如果你的模板和静态文件都位于Django项目目录内,请在settings.py中使用以下代码:
# settings.py
import os
PROJECT_DIR = os.path.dirname(__file__)
...
STATIC_DOC_ROOT = os.path.join(PROJECT_DIR, "static")
...
TEMPLATE_DIRS = (
os.path.join(PROJECT_DIR, "templates"),
)
致谢:我从视频教程 'Django从零开始' 中获得了这个提示。
安装Django Command Extensions和pygraphviz,然后输入以下命令以获得一个非常好看的Django模型可视化:
./manage.py graph_models -a -g -o my_project.png
使用django-annoying的render_to
装饰器代替render_to_response
。
@render_to('template.html')
def foo(request):
bars = Bar.objects.all()
if request.user.is_authenticated():
return HttpResponseRedirect("/some/url/")
else:
return {'bars': bars}
# equals to
def foo(request):
bars = Bar.objects.all()
if request.user.is_authenticated():
return HttpResponseRedirect("/some/url/")
else:
return render_to_response('template.html',
{'bars': bars},
context_instance=RequestContext(request))
编辑提示:返回一个HttpResponse(例如重定向)将会打破装饰器并且与你的预期一样工作。
我在我的网站模板中使用了一组自定义标签。为了实现自动加载(记得要DRY),我找到了以下方法:
from django import template
template.add_to_builtins('project.app.templatetags.custom_tag_module')
如果你将这个代码放在默认加载的模块中(例如你的主urlconf文件),你就可以在任何模板中使用来自你的自定义标签模块的标签和过滤器,而不需要使用 {% load custom_tag_module %}
。template.add_to_builtins()
的参数可以是任何模块路径,你的自定义标签模块不必存在于特定应用程序中。例如,它也可以是项目根目录中的一个模块(例如'project.custom_tag_module'
)。Virtualenv虚拟环境 + Python = 救命稻草,如果你正在开发多个Django项目,并且它们并不都依赖于相同版本的Django/应用程序。
virtualenv myNewEnv --no-site-packages
; . myNewEnv/bin/activate
; pip install django
; 就可以了! - SingleNegationEliminationreverse
函数获取URL本身。在定义URL映射时,给你的URL命名。urlpatterns += ('project.application.views'
url( r'^something/$', 'view_function', name="url-name" ),
....
)
url
标签一起使用。url
标签... 他的立场是 URL 不应该改变(如果你想对用户友好)。 - TM.{% url path.to.view.name arg1 arg2 %}
http://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#url - SingleNegationEliminationenvironment.filters ['url'] = django.core.urlresolvers.reverse
,然后您可以在您的模板中像这样使用它:{{ 'view-name'|url(arg1, arg2)|e }}
(需要“e”来转义一些字符以包含在HTML中)。 - SingleNegationElimination不要自己编写登录页面。 如果你正在使用django.contrib.auth。
真正的、肮脏的秘密是,如果你也在使用django.contrib.admin,并且django.template.loaders.app_directories.load_template_source在你的模板加载器中,那么你也可以免费获取你的模板!
# somewhere in urls.py
urlpatterns += patterns('django.contrib.auth',
(r'^accounts/login/$','views.login', {'template_name': 'admin/login.html'}),
(r'^accounts/logout/$','views.logout'),
)
假设您有一个不同的用户模型,并且您想在每个响应中包含它。而不是这样做:
def myview(request, arg, arg2=None, template='my/template.html'):
''' My view... '''
response = dict()
myuser = MyUser.objects.get(user=request.user)
response['my_user'] = myuser
...
return render_to_response(template,
response,
context_instance=RequestContext(request))
上下文处理能够让你向模板中传递任何变量。我一般会将它们放在'my_project/apps/core/context.py'
这个文件里:
def my_context(request):
try:
return dict(my_user=MyUser.objects.get(user=request.user))
except ObjectNotFound:
return dict(my_user='')
settings.py
文件中,将以下行添加到您的TEMPLATE_CONTEXT_PROCESSORS
中。TEMPLATE_CONTEXT_PROCESSORS = (
'my_project.apps.core.context.my_context',
...
)
my_user
键。from django.utils.translation import ugettext_lazy as _
class Post(models.Model):
title = models.CharField(_('title'), max_length=255)
body = models.TextField(_('body'))
created = models.DateTimeField(auto_now_add=True)
你希望通知其中一个博客ping服务,告诉他们我们发布了新文章,重建最近的文章缓存,并发推特。使用信号(signal),你无需为Post类添加任何方法就可以完成以上所有操作。
import twitter
from django.core.cache import cache
from django.db.models.signals import post_save
from django.conf import settings
def posted_blog(sender, created=None, instance=None, **kwargs):
''' Listens for a blog post to save and alerts some services. '''
if (created and instance is not None):
tweet = 'New blog post! %s' instance.title
t = twitter.PostUpdate(settings.TWITTER_USER,
settings.TWITTER_PASSWD,
tweet)
cache.set(instance.cache_key, instance, 60*5)
# send pingbacks
# ...
# whatever else
else:
cache.delete(instance.cache_key)
post_save.connect(posted_blog, sender=Post)
通过定义该函数并使用post_init信号将函数连接到Post model并在保存后执行它。
在这里,我们可以使用post_init信号来将函数与Post model连接起来,并在其保存后执行。
j = lambda filename: os.path.join(PROJECT_DIR, filename)
。然后你只需要输入j("static")
。 - wr.