最喜欢的Django提示&特征吗?

灵感来自问题系列的隐藏特征…,我很想听听你最喜欢的Django技巧或你知道的不太为人所知但有用的功能。

  • 请在每个答案中只包含一个技巧。
  • 添加Django版本要求(如果有的话)。
62922 次浏览

我就从我自己的一个建议开始吧:)

在settings.py中使用os.path.dirname()来避免硬编码的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 From the Ground Up”中得到了这个提示。

使用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(例如重定向)将使装饰器短路,并像您期望的那样工作。

我喜欢使用Python调试器pdb来调试Django项目。

这是一个学习如何使用它的有用链接:http://www.ferg.org/papers/debugging_in_python.html

与Django一起使用Jinja2

如果你发现Django模板语言有极大的限制(就像我一样!),那么你不必被它所困。Django很灵活,模板语言与系统的其余部分是松散耦合的,所以只需插入另一种模板语言,并使用它来呈现http响应!

我使用Jinja2,它几乎就像一个增强版的django模板语言,它使用相同的语法,并允许你在if语句中使用表达式!不再制作自定义if标记,如if_item_in_list!你可以简单地说%{ if item in list %}{% if object.field < 10 %}

但这还不是全部;它有更多的功能来简化模板创建,我不能在这里一一介绍。

在视图代码中添加assert False来转储调试信息。

安装Django命令扩展pygraphviz,然后执行以下命令,得到一个非常漂亮的Django模型可视化:

./manage.py graph_models -a -g -o my_project.png

不要硬编码你的url !

使用url名字代替,并使用reverse函数来获取URL本身。

在定义URL映射时,为URL指定名称。

urlpatterns += ('project.application.views'
url( r'^something/$', 'view_function', name="url-name" ),
....
)

确保每个URL的名称是唯一的。

我通常有一个一致的格式“项目-应用程序-视图”,例如:“cbx-forum-thread”用于线程视图。

更新(无耻地窃取阿亚兹的加法):

此名称可用于带有url标签. xml文件的模板中。

不要编写自己的登录页面。如果你使用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'),
)

django.views.generic.list_detail.object_list——它提供了所有的逻辑&用于分页的模板变量(这是我已经写了上千遍的苦差事之一)。包装它允许你需要的任何逻辑。这个gem为我节省了很多时间调试“搜索结果”页面中的一个错误,并使视图代码在这个过程中更加清晰。

这将添加到上面关于Django URL名称和反向URL调度的回复。

URL名称也可以在模板中有效地使用。例如,对于一个给定的URL模式:

url(r'(?P<project_id>\d+)/team/$', 'project_team', name='project_team')

你可以在模板中有以下内容:

<a href="{% url project_team project.id %}">Team</a>

当我开始的时候,我不知道有Paginator,确保你知道它的存在!!

在Django和其他应用程序之间交换数据时,request.raw_post_data是一个好朋友。使用它来接收和自定义处理(比如XML数据)。

< p >文档: http://docs.djangoproject.com/en/dev/ref/request-response/ < / p >

django.db.models.get_model允许你在不导入模型的情况下检索模型。

James展示了它是多么方便:Django提示:编写更好的模板标签-迭代4

使用django模板代替as_(ul|table|p)()

这篇文章展示了如何使用模板来呈现customforms而不是as_p()as_table()

要让它发挥作用,就要改变

  • __abc0 __abc2 __abc1
  • __abc0 __abc2 __abc1

使用isapi-wsgidjango-pyodbc在Windows上使用IIS和SQL Server运行Django !

设计应用程序在开始设计你的网站时非常有用。一旦导入,你可以添加它来生成示例文本:

{% load webdesign %}
{% lorem 5 p %}

在我的站点模板中,我使用了一组自定义标记。寻找一种自动加载的方法(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/应用程序。

使用Django调试工具栏。例如,它允许查看在呈现视图时执行的所有SQL查询,您还可以查看其中任何一个的堆栈跟踪。

我没有足够的声誉来回复有问题的评论,但重要的是要注意,如果你要使用金贾的,它不支持模板块名称中的'-'字符,而Django支持。这给我带来了很多问题,并浪费了很多时间试图追踪它生成的非常模糊的错误消息。

刚刚找到这个链接:http://lincolnloop.com/django-best-practices/#table-of-contents -“Django最佳实践”。

django-admin文档:

如果你使用Bash shell,可以考虑安装Django Bash完成脚本,它位于Django发行版的extras/django_bash_completion中。它支持django-admin.pymanage.py命令的制表符补全,所以你可以,例如…

  • django-admin.py类型。
  • 按[TAB]查看所有可用选项。
  • 输入sql,然后输入[TAB],查看所有名称以sql开头的可用选项。

上下文处理器非常棒。

假设你有一个不同的用户模型,你想包括 在每个回应中。而不是这样:

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键。

信号赢。

几个月前我写了一篇关于这方面的博客文章,所以我只是要剪切和粘贴:

Django为你提供了几个信号 令人难以置信的有用。你有能力提前做好事情 发布保存,初始化,删除,甚至当请求正在进行时 处理。我们先不讲概念 演示如何使用这些。假设我们有一个博客

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)
所以你想以某种方式通知众多博客中的一个 服务我们已经做了一个新的帖子,重建最近 帖子缓存,并tweet关于它。你有信号 无需添加任何内容即可完成所有这些操作的能力

.
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模型 并在保存后执行它

我从sorl-thumbnails应用程序的文档中学到了这个。你可以在模板标记中使用"as"关键字来在模板的其他地方使用调用的结果。

例如:

{% url image-processor uid as img_src %}
<img src="{% thumbnail img_src 100x100 %}"/>

这一点在Django templatetag文档中提到过,但仅用于引用循环。他们并没有说你也可以在其他地方使用它(任何地方?)

因为Django的“视图”只需要是返回HttpResponse的可调用对象,你可以很容易地创建基于类的视图,就像Ruby on Rails和其他框架中的那样。

有几种方法可以创建基于类的视图,下面是我最喜欢的:

from django import http


class RestView(object):
methods = ('GET', 'HEAD')


@classmethod
def dispatch(cls, request, *args, **kwargs):
resource = cls()
if request.method.lower() not in (method.lower() for method in resource.methods):
return http.HttpResponseNotAllowed(resource.methods)
try:
method = getattr(resource, request.method.lower())
except AttributeError:
raise Exception("View method `%s` does not exist." % request.method.lower())
if not callable(method):
raise Exception("View method `%s` is not callable." % request.method.lower())
return method(request, *args, **kwargs)


def get(self, request, *args, **kwargs):
return http.HttpResponse()


def head(self, request, *args, **kwargs):
response = self.get(request, *args, **kwargs)
response.content = ''
return response

您可以在基本视图中添加各种其他东西,如条件请求处理和授权。

一旦你设置好了你的视图,你的urls.py将看起来像这样:

from django.conf.urls.defaults import *
from views import MyRestView


urlpatterns = patterns('',
(r'^restview/', MyRestView.dispatch),
)

使用信号动态添加访问方法。

我在django-photologue中看到过这种技术:对于添加的任何Size对象,post_init信号将向Image模型添加相应的方法。 如果你添加一个站点巨大的,在大分辨率下检索图片的方法将是image.get_giant_url().

这些方法是通过从post_init信号调用add_accessor_methods生成的:

def add_accessor_methods(self, *args, **kwargs):
for size in PhotoSizeCache().sizes.keys():
setattr(self, 'get_%s_size' % size,
curry(self._get_SIZE_size, size=size))
setattr(self, 'get_%s_photosize' % size,
curry(self._get_SIZE_photosize, size=size))
setattr(self, 'get_%s_url' % size,
curry(self._get_SIZE_url, size=size))
setattr(self, 'get_%s_filename' % size,
curry(self._get_SIZE_filename, size=size))

请参阅photonology .models的源代码的实际用法。

使用djangorecipe来管理你的项目

  • 如果你正在编写一个新的应用程序,这个方法可以让你在项目之外非常容易地测试它
  • 它允许你管理项目的依赖关系(例如,它应该依赖于哪个版本的应用程序)

你要做的就是这样开始:

  1. 为你的新网站(或图书馆)创建一个文件夹
  2. 创建一个包含以下内容的build - out.cfg:

    
    [buildout]
    parts=django
    
    
    [django]
    recipe=djangorecipe
    version=1.1.1
    project=my_new_site
    settings=development
    
  3. Grab a bootstrap.py to get a local installation of buildout and place it within your directory. You can either go with the official one (sorry, Markdown didn't like part of the full link :-/ ) or with one that uses distribute instead of setuptools as described by Reinout van Rees.
  4. python bootstrap.py (or python bootstrap_dev.py if you want to use distribute).
  5. ./bin/buildout

That's it. You should now have a new folder "my_new_site", which is your new django 1.1.1 project, and in ./bin you will find the django-script which replaces the manage.py on a normal installation.

What's the benefit? Let's say you want to use something like django-comment-spamfighter in your project. All you'd have to do is change your buildout.cfg to something like this:


[buildout]
parts=django


[django]
recipe=djangorecipe
version=1.1.1
project=my_new_site
settings=development
eggs=
django-comments-spamfighter==0.4

请注意,我所做的只是添加了最后两行,表示django部分在0.4版中也应该有django-comments-spamfighter包。下次运行./bin/buildout时,buildout将下载该包并修改./bin/django,将其添加到其PYTHONPATH中。

Djangorecipe也适用于用mod_wsgi部署你的项目。只需将wsgi=true设置添加到build - out.cfg中的django-part和“django. cfg”。Wsgi "将出现在你的。/bin文件夹中:-)

如果你将test选项设置为应用程序列表,djangorecipe将为你创建一个漂亮的包装器,为项目中列出的应用程序运行所有测试。

如果你想在一个独立的环境中开发一个单独的应用程序进行调试等,Jakob Kaplan-Moss有一个相当完整的他的博客教程

不要使用render_to_response将上下文绑定到模板并渲染它(这是Django文档通常显示的),而是使用通用视图direct_to_template。它所做的事情与render_to_response所做的事情相同,但它也自动将RequestContext添加到模板上下文中,隐式地允许使用上下文处理器。你可以使用render_to_response手动完成,但是为什么要麻烦呢?这只是另一个要记住的步骤和另一个LOC。除了使用上下文处理器,在模板中使用RequestContext还允许你做以下事情:

<a href="\{\{MEDIA_URL}}images/frog.jpg">A frog</a>

这是非常有用的。事实上,+1在一般的视图上。对于简单的应用程序,Django文档大多将它们作为快捷方式显示,甚至没有views.py文件,但你也可以在自己的视图函数中使用它们:

from django.views.generic import simple


def article_detail(request, slug=None):
article = get_object_or_404(Article, slug=slug)
return simple.direct_to_template(request,
template="articles/article_detail.html",
extra_context={'article': article}
)

不要在本地主机上运行Django开发服务器,而是在一个合适的网络接口上运行。例如:

python manage.py runserver 192.168.1.110:8000

python manage.py runserver 0.0.0.0:8000

然后,您不仅可以轻松地使用Fiddler (http://www.fiddler2.com/fiddler2/)或其他工具,如HTTP调试器(http://www.httpdebugger.com/)来检查您的HTTP头,而且还可以从LAN上的其他机器访问您的开发站点进行测试。

确保你有防火墙保护,尽管开发服务器是最小的,而且相对安全。

使用IPython在任何级别跳转到代码中,并使用IPython的功能进行调试。一旦你安装了IPython,就把这段代码放在你想调试的地方:

from IPython.Shell import IPShellEmbed; IPShellEmbed()()

然后,刷新页面,转到runserver窗口,您将进入一个交互式IPython窗口。

我有一个片段设置在TextMate,所以我只是键入ipshell和点击标签。没有它我活不下去。

这是一种非常简单的方法,永远不必在python shell中再次导入另一个模型。

首先,安装IPython(如果你不使用IPython,你有什么问题?)接下来,在django项目目录中创建一个python脚本ipythonrc.py,其中包含以下代码:

from django.db.models.loading import get_models
for m in get_models():
globals()[m.__name__] = m
#NOTE: if you have two models with the same name you'll only end up with one of them

然后,在你的~/。ipython/ipythonrc文件,将以下代码放在“要加载和执行的Python文件”部分:

execfile /path/to/project/ipythonrc.py

现在,每次你启动IPython或运行./manage.py shell时,你的所有模型都已经导入并可以使用了。不需要再导入另一个模型。

您还可以将经常执行的任何其他代码放在ipythonrc.py文件中,以节省时间。

每个人都知道有一个可以使用“manage.py runserver”运行的开发服务器,但是你知道还有一个用于提供静态文件(CSS / JS / IMG)的开发视图吗?

新手总是感到困惑,因为Django没有提供任何提供静态文件的方法。这是因为开发团队认为这是实际Web服务器的工作。

但是在开发时,你可能不想设置Apache + mod_wisi,它很重。然后你只需要在urls.py中添加以下内容:

(r'^site_media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': '/path/to/media'}),

您的CSS / JS / IMG将在www.yoursite.com/site_media/上提供。

当然,不要在生产环境中使用它。

运行一个开发SMTP服务器,它只输出发送给它的任何内容(如果您不想在开发服务器上实际安装SMTP)。

命令行:

python -m smtpd -n -c DebuggingServer localhost:1025

在自定义视图装饰器中使用wraps装饰器来保留视图的名称、模块和文档字符串。如。

try:
from functools import wraps
except ImportError:
from django.utils.functional import wraps  # Python 2.3, 2.4 fallback.


def view_decorator(fun):
@wraps(fun)
def wrapper():
# here goes your decorator's code
return wrapper

当心:如果作者没有定义__name__属性,则不会在基于类的视图(具有__call__方法定义的视图)上工作。作为一种变通方法:

from django.utils.decorators import available_attrs
...
@wraps(fun, assigned=available_attrs(fun))

在init上更改Django表单字段属性

有时向Form类传递额外的参数是有用的。

from django import forms
from mymodels import Group


class MyForm(forms.Form):
group=forms.ModelChoiceField(queryset=None)
email=forms.EmailField()
some_choices=forms.ChoiceField()




def __init__(self,my_var,*args,**kwrds):
super(MyForm,self).__init__(*args,**kwrds)
self.fields['group'].queryset=Group.objects.filter(...)
self.fields['email'].widget.attrs['size']='50'
self.fields['some_choices']=[[x,x] for x in list_of_stuff]

来源:Dzone片段

PyCharm IDE是一个很好的编码环境,尤其是调试环境,内置了对Django的支持。

Django调试工具栏真的很棒。它实际上并不是一个工具栏,而是一个侧栏,告诉您是什么带来了您正在查看的页面的各种信息——DB查询、发送到模板的上下文变量、信号等等。

使用xml_models创建使用XML REST API后端(而不是SQL后端)的Django模型。这是非常有用的,特别是在对第三方api建模时——你会得到你习惯的所有相同的QuerySet语法。您可以从PyPI安装它。

来自API的XML:

<profile id=4>
<email>joe@example.com</email>
<first_name>Joe</first_name>
<last_name>Example</last_name>
<date_of_birth>1975-05-15</date_of_birth>
</profile>

现在在python中:

class Profile(xml_models.Model):
user_id = xml_models.IntField(xpath='/profile/@id')
email = xml_models.CharField(xpath='/profile/email')
first = xml_models.CharField(xpath='/profile/first_name')
last = xml_models.CharField(xpath='/profile/last_name')
birthday = xml_models.DateField(xpath='/profile/date_of_birth')


finders = {
(user_id,):  settings.API_URL +'/api/v1/profile/userid/%s',
(email,):  settings.API_URL +'/api/v1/profile/email/%s',
}


profile = Profile.objects.get(user_id=4)
print profile.email
# would print 'joe@example.com'

它还可以处理关系和集合。我们每天都在大量使用的产品代码中使用它,所以即使它是测试版,它也是非常有用的。它还有一组很好的存根,可以在测试中使用。

(免责声明:虽然我不是这个库的作者,但我现在是一个提交者,已经进行了一些小的提交)

在urlconf中使用reverse。

这是我不明白为什么它不是默认的那些技巧之一。

这是我捡到它的地方的链接: http://andr.in/2009/11/21/calling-reverse-in-django/ < / p >

下面是代码片段:

from django.conf.urls.defaults import *
从django.core.urlresolvers导入反向
从django.utils.functional导入lazy
django。http导入HttpResponse


Reverse_lazy = lazy(reverse, str)


Urlpatterns = patterns(",
url(r'^comehere/', lambda request: HttpResponse('Welcome!'), name='comehere'),
url (r“^ $”,“django.views.generic.simple.redirect_to”,
{'url': reverse_lazy('comehere')}, name='root')
) < /代码> < / pre > < /引用>

为具有相同结构的遗留表集创建动态模型:

class BaseStructure(models.Model):
name = models.CharField(max_length=100)
address = models.CharField(max_length=100)


class Meta:
abstract=True


class DynamicTable(models.Model):
table_name = models.CharField(max_length=20)


def get_model(self):
class Meta:
managed=False
table_name=self.table_name


attrs = {}
attrs['Meta'] = Meta


# type(new_class_name, (base,classes), {extra: attributes})
dynamic_class = type(self.table_name, (BaseStructure,), attrs)
return dynamic_class


customers = DynamicTable.objects.get(table_name='Customers').get_model()
me = customers.objects.get(name='Josh Smeaton')
me.address = 'Over the rainbow'
me.save()

这假设您拥有具有相同结构的遗留表。您不需要创建一个模型来包装每个表,而是定义一个基本模型,并动态构造与特定表交互所需的类。

从settings.py中删除数据库访问信息

我在Django站点的settings.py中做的一件事是从/etc中的一个文件中加载数据库访问信息。这样,每台机器的访问设置(数据库主机、端口、用户名、密码)都是不同的,并且像密码这样的敏感信息不在我的项目存储库中。您可能希望以类似的方式限制对工作者的访问,即让他们使用不同的用户名连接。

你也可以通过环境变量传递数据库连接信息,甚至只是一个配置文件的键或路径,并在settings.py中处理它。

例如,下面是我如何拉入我的数据库配置文件:

g = {}
dbSetup = {}
execfile(os.environ['DB_CONFIG'], g, dbSetup)
if 'databases' in dbSetup:
DATABASES = dbSetup['databases']
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
# ...
}
}

不用说,你需要确保DB_CONFIG中的文件不能被db管理员和Django本身之外的任何用户访问。默认情况下,Django应该参考开发人员自己的测试数据库。可能还有一个更好的解决方案,使用ast模块而不是execfile,但我还没有研究它。

我做的另一件事是为DB管理任务使用单独的用户。在我的manage.py中,我添加了以下序言:

# Find a database configuration, if there is one, and set it in the environment.
adminDBConfFile = '/etc/django/db_admin.py'
dbConfFile = '/etc/django/db_regular.py'
import sys
import os
def goodFile(path):
return os.path.isfile(path) and os.access(path, os.R_OK)
if len(sys.argv) >= 2 and sys.argv[1] in ["syncdb", "dbshell", "migrate"] \
and goodFile(adminDBConfFile):
os.environ['DB_CONFIG'] = adminDBConfFile
elif goodFile(dbConfFile):
os.environ['DB_CONFIG'] = dbConfFile

其中,/etc/django/db_regular.py中的配置是针对只有SELECT、INSERT、UPDATE和DELETE权限的Django数据库用户,而/etc/django/db_admin.py是针对拥有这些权限以及CREATE、DROP、INDEX、ALTER和LOCK表的用户。(migrate命令来自。)这在运行时为我提供了一些保护,防止Django代码弄乱我的模式,并限制了SQL注入攻击可能造成的损害(尽管您仍然应该检查和过滤所有用户输入)。

(从我的答案另一个问题复制)

django_extensions附带的./manage.py runserver_plus功能真的很棒。

它创建了一个增强的调试页面,其中使用Werkzeug调试器为堆栈中的每个点创建交互式调试控制台(见截图)。它还提供了一个非常有用的调试方法dump(),用于显示关于对象/帧的信息。

enter image description here

要安装,您可以使用pip:

pip install django_extensions
pip install Werkzeug

然后将'django_extensions'添加到settings.py中的INSTALLED_APPS元组中,并使用新扩展启动开发服务器:

./manage.py runserver_plus

这将改变调试的方式。

使用“apps”文件夹来组织应用程序,而不需要编辑PYTHONPATH

当我想这样组织我的文件夹时,这个方法就很方便了:

apps/
foo/
bar/
site/
settings.py
urls.py

无需重写PYTHONPATH,也无需在每次导入时都添加应用程序,比如:

from apps.foo.model import *
from apps.bar.forms import *

在你的settings.py中添加

import os
import sys
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(PROJECT_ROOT, "apps"))

你已经准备好了:-)

我在http://codespatter.com/2009/04/10/how-to-add-locations-to-python-path-for-reusable-django-apps/看到这个

在Django 1.2+中使用.exists(),在以前的版本中使用.count(),而不是计算整个queryset来检查是否返回任何结果。

exists()和count()都清除order by子句,并从DB中检索单个整数。然而exists()将总是返回1,而as count可能会返回更高的值,对这些值将手动应用限制。exists()中使用的has_result和count()中使用的get_count的源代码。

因为它们都返回一个整数,所以没有模型实例化,在内存中加载模型属性,也没有大的TextFields在你的DB和应用程序之间传递。

如果你已经计算了查询,.count()计算len(cached_result), .exists()计算bool(cached_result)

效率不高—例1

books = Books.objects.filter(author__last_name='Brown')
if books:
# Do something

效率不高——例2

books = Books.objects.filter(author__last_name='Brown')
if len(books):
# Do something

高效-例1

books = Books.objects.filter(author__last_name='Brown')
if books.count():
# Do something

高效-例2

books = Books.objects.filter(author__last_name='Brown')
if books.exists():
# Do something

来自https://github.com/django-extensions/django-extensionsdjango_extensions非常棒。

一些漂亮的./manage.py命令:

  • shell_plus - autoimport所有INSTALLED_APPS中的模型
  • show_urls打印项目中所有应用程序中定义的所有url
  • runscript -在项目上下文中运行任何脚本(你可以使用模型和其他django相关模块)

PyCharm和Wingware IDE是很好的工具,如果你有钱支付许可证。

由于我是一个糟糕的开发人员,我使用PyDev中Eclipse

当将变量从视图传递到模板时,输入响应字典会变得很乏味。我发现使用locals()一次性传递所有局部变量很好。

def show_thing(request, thing_id):
thing = Thing.objects.get(pk=thing_id)
return render_to_response('templates/things/show.html', locals())

(本质上不是一个隐藏的特性,但对于刚接触Python和Django的人来说还是很有帮助的。)

编辑:显然,显式比隐式更好,但这种方法在开发过程中是有帮助的。

使用数据库迁移。使用

有点晚了。但是Django Canvas最近出来了,它值得在这里占有一席之地。

不要用django-admin.py startproject开始你的项目。相反,你可以使用像Django帆布这样的东西来帮助将一个空白项目与你需要的模块拼凑在一起。

你去那个网站,勾选一些选项,然后下载一个空白项目,很简单。

它具有所有常见的东西,如南模式迁移和命令扩展,以及这里提到的许多其他最佳实践。另外,它有一个很棒的start.sh/shart.bat脚本,可以安装python, virtualenv, pip, django和任何你需要从windows, osx或linux的新副本开始的东西。

如果您对模型进行更改

./manage.py dumpdata appname > appname_data.json
./manage.py reset appname
django-admin.py loaddata appname_data.json

dir (),提高ValueError ()

为了在开发过程中调试/探索事物的状态,我使用了以下技巧:

...
to_see = dir(inspect_this_thing)
to_see2 = inspect_this_thing.some_attribute
raise ValueError("Debugging")
...

当你处理django中没有很好文档的部分时,这是特别有用的。changed_fields是我最近使用的一个)。

当地人()。

使用python内置的locals()命令为你创建一个字典,而不是为模板上下文写出每个变量:

#This is tedious and not very DRY
return render_to_response('template.html', {"var1": var1, "var2":var2}, context_instance=RequestContext(request))


#95% of the time this works perfectly
return render_to_response('template.html', locals(), context_instance=RequestContext(request))


#The other 4.99%
render_dict = locals()
render_dict['also_needs'] = "this value"
return render_to_response('template.html', render_dict, context_instance=RequestContext(request))

在生产环境中自动设置'DEBUG'属性(settings.py)

import socket


if socket.gethostname() == 'productionserver.com':
DEBUG = False
else:
DEBUG = True

: http://nicksergeant.com/2008/automatically-setting-debug-in-your-django-app-based-on-server-hostname/

Django没有应用程序设置,所以我做了自己的app_settings.py检测。 在settings.py的底部,我添加了这段代码:

import sys, os
# Append application settings without triggering the __init__.
for installed_app in INSTALLED_APPS:
# Ignore django applications
if not installed_app.startswith('django.'):
# Find the app (and the settings file)
for path in sys.path:
path = os.path.join(path, installed_app, 'app_settings.py')
if os.path.isfile(path):
# Application settings found
exec open(path).read()

它在所有的INSTALLED_APPS中检测app_settings.py。它将读取app_settings文件的内容并内联执行它,而不是导入它。如果直接导入app_settings,将会引发所有的Django导入错误(因为Django还没有初始化)。

所以我的app/app_settings.py看起来是这样的:

MIDDLEWARE_CLASSES += (
'app.middleware.FancyMiddleware',
)

现在应用程序只需要添加到INSTALLED_APPS,而不是找到所有的应用程序设置,并将它们添加到settings.py(中间件,url…)

注意:如果Django有一个钩子来附加额外的设置会更好,这样应用程序设置就可以在启动时(或运行时)添加。

使用异步任务。使用芹菜

如果你还没有读过Unbreaking Django的话。它包含关于django陷阱的有用信息很多