关于python:最喜欢的Django Tips&

Favorite Django Tips & Features?

受问题系列"隐藏的……特征"的启发,我很想知道你最喜欢的django技巧,或者你知道的一些不太知名但有用的特征。

  • 请每个答案只包括一个提示。
  • 如果有,添加django版本要求。

我要从我自己的小费开始:)

在settings.py中使用os.path.dirname()以避免硬编码的dirname。

不要在设置中硬编码路径。如果要在不同的位置运行项目,请复制。如果模板和静态文件位于django项目目录中,请使用settings.py中的以下代码:

1
2
3
4
5
6
7
8
9
# 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命令扩展和pygraphviz,然后发出以下命令以获得非常漂亮的django模型可视化效果:

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


使用django恼人的render_to装饰器而不是render_to_response

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@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(如重定向)会使装饰器短路,并按预期工作。


我在网站的所有模板上都使用了一组自定义标记。寻找一种自动加载的方法(干燥,记得吗?),我发现了以下内容:

1
2
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=life saver如果您正在处理多个django项目,并且可能它们都不依赖于同一版本的django/an应用程序。


不要硬编码你的网址!

使用url名称代替,使用reverse函数获取url本身。

定义URL映射时,请为URL命名。

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

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

我通常有一个一致的格式"项目应用视图",例如线程视图的"CBX论坛线程"。

更新(无耻地窃取了Ayaz的附加内容):

此名称可以在带有url标记的模板中使用。


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


不要编写自己的登录页面。如果您正在使用django.contrib.auth。

真正肮脏的秘密是,如果您还使用django.contrib.admin和django.template.loaders.app_directories.load_template_source,那么您也可以免费获取模板!

1
2
3
4
5
# somewhere in urls.py
urlpatterns += patterns('django.contrib.auth',
    (r'^accounts/login/$','views.login', {'template_name': 'admin/login.html'}),
    (r'^accounts/logout/$','views.logout'),
)


上下文处理器非常棒。

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

1
2
3
4
5
6
7
8
9
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里:

1
2
3
4
5
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中添加以下行

1
2
3
4
TEMPLATE_CONTEXT_PROCESSORS = (
    'my_project.apps.core.context.my_context',
    ...
)

现在,每次发出请求时,都会自动包含my_user键。

也表示胜利。

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

开箱即用的Django给你几个信号非常有用。你有能力在post save、init、delete,甚至当请求处理。所以让我们远离这些概念演示如何使用这些。假设我们有一个博客

1
2
3
4
5
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服务我们已经发了一个新的帖子,重建最近的发布缓存,并在tweet上发布。好吧,有信号的话不需要添加任何方法到Post类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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模型保存后执行。


当我刚开始的时候,我不知道有一个异教徒,确保你知道它的存在!!


使用ipython可以在任何级别跳到代码中,并使用ipython的强大功能进行调试。一旦安装了IPython,只要将此代码放入要调试的任何位置即可:

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

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

我在textmate中设置了一个代码片段,所以我只需键入ipshell并点击tab。没有它我活不下去。


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

命令行:

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


从Django管理文档:

如果使用bash shell,请考虑安装django bash完成脚本,该脚本位于django发行版的extras/django_bash_completion中。它支持django-admin.pymanage.py命令的制表完成,因此您可以,例如…

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


django ou扩展版附带的./manage.py runserver_plus工具真是太棒了。

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

enter image description here

要安装,可以使用pip:

1
2
pip install django_extensions
pip install Werkzeug

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

1
./manage.py runserver_plus

这将更改调试方式。


我喜欢使用python调试器pdb来调试django项目。

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


当试图在Django和另一个应用程序之间交换数据时,request.raw_post_data是一个好朋友。使用它来接收和定制过程,比如XML数据。

文档:http://docs.djangoproject.com/en/dev/ref/request-response(请求-响应)/


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


在Django旁边使用Jinja2。

如果您发现django模板语言非常限制(像我!)那你就不必被它困住了。Django是灵活的,模板语言与系统的其他部分松散耦合,因此只需插入另一种模板语言,并使用它来呈现HTTP响应!

我使用jinja2,它几乎就像是Django模板语言的加电版本,它使用相同的语法,并且允许您在if语句中使用表达式!如果标签如if_item_in_list,就不再定制了!你可以简单地说%{ if item in list %}{% if object.field < 10 %}

但这并不是全部;它有更多的特性来简化模板的创建,我不能在这里浏览所有的特性。


这增加了上面关于django url名称和反向url调度的回复。

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

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

模板中可以包含以下内容:

1
Team

由于django"views"只需要是返回httpresponse的可调用的,所以您可以轻松地创建基于类的视图,如RubyonRails和其他框架中的视图。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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就会变成这样:

1
2
3
4
5
6
from django.conf.urls.defaults import *
from views import MyRestView

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


不要使用render_to_response将上下文绑定到模板并呈现它(这是django文档通常显示的内容),而是使用通用视图direct_to_template。它与render_to_response做的相同,但它也自动将requestContext添加到模板上下文,隐式地允许使用上下文处理器。您可以使用render_to_response手动执行此操作,但是为什么要麻烦呢?这只是另一个需要记住的步骤和另一个位置。除了使用上下文处理器之外,在模板中使用requestContext还允许您执行以下操作:

1
A frog

这是非常有用的。实际上,一般来说+1是通用视图。Django文档大多将它们显示为快捷方式,即使对于简单的应用程序没有views.py文件,也可以在自己的视图功能中使用它们:

1
2
3
4
5
6
7
8
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}
    )


我没有足够的声誉来回复有关的评论,但需要注意的是,如果您要使用jinja,它不支持模板块名称中的"-"字符,而django支持。这给我带来了很多问题,也浪费了很多时间来跟踪它生成的非常模糊的错误消息。


每个人都知道有一个可以用"manage.py run server"运行的开发服务器,但是您知道有一个为静态文件(css/js/img)提供服务的开发视图吗?

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

但是在开发时,您可能不想设置apache+mod_wisgi,这很重。然后您可以将以下内容添加到urls.py中:

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

您的css/js/img将在www.your site.com/site_media/上提供。

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


WebDesign应用程序在开始设计网站时非常有用。导入后,可以添加此内容以生成示例文本:

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


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

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


我从SORL缩略图应用程序的文档中学习了这个。您可以使用模板标记中的"as"关键字来使用模板中其他地方的调用结果。

例如:

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

在传递django templatetag文档时提到了这一点,但仅参考循环。他们不会说你可以在其他地方(任何地方)使用这个。也。


pycharm-ide是一个很好的编程环境,特别是调试环境,内置了对django的支持。


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


使用数据库迁移。南部使用。


使用XML_模型创建使用XML REST API后端(而不是SQL后端)的Django模型。这非常有用,尤其是在建模第三方API时——您得到的查询集语法完全相同。您可以从pypi安装它。

来自API的XML:

1
2
3
4
5
6
<profile id=4>
    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中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 '[email protected]'

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

(免责声明:虽然我不是此库的作者,但我现在是一名提交者,做了一些小的承诺)


刚刚找到这个链接:http://lincolnloop.com/django best practices/目录-"django best practices"。


在Django1.2+中使用.exists(),在以前的版本中使用.count(),而不是评估整个查询集以检查是否返回任何结果。

exists()和count()都清除order by子句,并从db中检索单个整数。但是exists()将始终返回1,其中as count可能返回更高的值,对这些值手动应用限制。source for has_result used in exists()and get_count used in count()for好奇的人。

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

如果已经计算了查询,.count()计算len(缓存的结果),.exists()计算bool(缓存的结果)

不高效-示例1

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

不高效-示例2

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

高效-示例1

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

高效-示例2

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


如果对模型进行更改

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


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

我在Django站点的settings.py中做的一件事是从/etc中的文件加载数据库访问信息。这样,每台计算机的访问设置(数据库主机、端口、用户名、密码)可能会有所不同,而诸如密码之类的敏感信息不在我的项目的存储库中。您可能希望以类似的方式限制对工作人员的访问,方法是让他们使用不同的用户名进行连接。

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

例如,以下是我拉入数据库配置文件的方式:

1
2
3
4
5
6
7
8
9
10
11
12
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 admins和django本身之外,任何用户都无法访问DB_CONFIG中的文件。默认情况下,应该将django引用到开发人员自己的测试数据库。使用ast模块而不是execfile模块可能还有更好的解决方案,但我还没有研究过。

我要做的另一件事是使用单独的用户执行数据库管理任务,而不是其他任何任务。在我的manage.py中,我添加了以下前言:

1
2
3
4
5
6
7
8
9
10
11
12
# 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 photologue中看到了这种技术:对于添加的任何大小的对象,post-init信号都会将相应的方法添加到图像模型中。如果您添加一个站点巨人,那么以巨分辨率检索图片的方法将是image.get_giant_url()

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

1
2
3
4
5
6
7
8
9
10
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))

实际使用请参见photologue.models的源代码。


不要在本地主机上运行django dev服务器,而是在适当的网络接口上运行它。例如:

1
python manage.py runserver 192.168.1.110:8000

1
python manage.py runserver 0.0.0.0:8000

然后,您不仅可以轻松地使用fiddler(http://www.fiddler2.com/fiddler2/)或其他工具(如http debugger(http://www.http debugger.com/)来检查您的http头,还可以从LAN上的其他计算机访问您的dev站点进行测试。

尽管dev服务器是最小且相对安全的,但是请确保您受到防火墙的保护。


在自定义视图装饰器中使用wraps装饰器来保留视图的名称、模块和docstring。例如。

1
2
3
4
5
6
7
8
9
10
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__方法定义的视图)上工作。作为解决方法使用:

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

Django调试工具栏非常棒。它实际上并不是一个工具栏,而是一个侧窗格,告诉您有关所查看页面的各种信息—数据库查询、发送到模板的上下文变量、信号等等。


使用"apps"文件夹组织应用程序而不编辑pythonpath

当我想像这样整理我的文件夹时,这很方便:

1
2
3
4
5
6
apps/
    foo/
    bar/
site/
settings.py
urls.py

无需覆盖pythonpath或在每次导入时添加应用程序,如:

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

在您的设置中.py add

1
2
3
4
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上看到了这个。/


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

1
2
3
4
5
6
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模板呈现表单,而不是使用(ul table p)()。

本文介绍了如何用模板来代替as_p()as_table()

改变它的工作方式

  • from django import newforms as formsfrom django import forms
  • from django.newforms.forms import BoundFieldfrom django.forms.forms import BoundField

在URLCONF中使用REVERSE。

这是其中一个技巧,我不明白为什么它不是默认的。

这里有一个链接,指向我在哪里找到它:http://andr.in/2009/11/21/calling-reverse-in-django/

下面是代码段:

1
2
3
4
5
6
7
8
9
10
11
12
from django.conf.urls.defaults import *
from django.core.urlresolvers import reverse
from django.utils.functional import lazy
from django.http import 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')
)


使用DjangoreCipe管理项目

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

你要开始做的就是:

  • 为新网站(或库)创建文件夹
  • 创建一个buildout.cfg,其中包含以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    [buildout]
    parts=django

    [django]
    recipe=djangorecipe
    version=1.1.1
    project=my_new_site
    settings=development
  • 抓取一个bootstrap.py以获得buildout的本地安装,并将其放在目录中。您可以选择正式的(抱歉,Markdown不喜欢完整链接的一部分:-/)或使用Distribute而不是Reiniout van Rees描述的安装工具。
  • python bootstrap.py(或python bootstrap_dev.py,如果您想使用distribute)。
  • ./bin/buildout
  • 就是这样。现在,您应该有一个新文件夹"我的新站点",这是您的新Django 1.1.1项目,在./bin中,您将找到在正常安装中替换manage.py的django脚本。

    有什么好处?假设您希望在您的项目中使用类似于django comment spamfighter的东西。你要做的就是把buildout.cfg改成这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [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设置添加到buildout.cfg的django部分,您的./bin文件夹中将显示一个"django.wsgi":-)

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

    如果你想在一个独立的环境中开发一个应用程序来进行调试等,Jakob Kaplan Moss在他的博客上有一个非常完整的教程。


    这是一种非常简单的方法,不必再在Python外壳中导入另一个模型。

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

    1
    2
    3
    4
    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文件"部分:

    1
    execfile /path/to/project/ipythonrc.py

    现在,每次启动ipython或运行./manage.py shell时,您的所有模型都已导入并准备好使用。不需要再导入另一个模型。

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


    更改init上的django表单字段属性

    有时向窗体类传递额外的参数很有用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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和Wingware IDE是一个很好的工具,如果你有钱支付许可证。

    因为我是一个糟糕的开发人员,所以我将pydev与eclipse结合使用。


    来自https://github.com/django-extensions/django-extensions的django_extensions非常好。

    很少有漂亮的./manage.py命令:

    • shell_plus—从所有已安装的应用程序自动导入模型
    • show_urls-打印项目中所有应用程序中定义的所有URL
    • runscript—在项目上下文中运行任何脚本(您可以使用模型和其他与django相关的模块)

    使用isapi wsgi和django pyodbc在Windows上使用IIS和SQL Server运行django!


    参加聚会有点晚。但姜戈画布最近问世了,它应该在这里占有一席之地。

    不要从django-admin.py startproject开始你的项目。相反,您可以使用类似于DjangoCanvas的东西来帮助将一个空白项目与您需要的模块组合在一起。

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

    它具有所有常见的功能,比如南模式迁移和命令扩展,以及这里提到的许多其他最佳实践。另外,它还有一个很好的start.sh/shart.bat脚本,可以安装python、virtualenv、pip、django以及从新版本的Windows、OSX或Linux开始所需的一切。


    如果你还没读过的话,请继续读《姜戈》。它包含了很多关于Django陷阱的有用信息。


    使用异步任务。芹菜用


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    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()

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


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

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

    (本身并不是隐藏的特性,但是对于Python和/或Django来说,它还是很有用的。)

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


    dir()提升值错误()

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

    1
    2
    3
    4
    5
    ...
      to_see = dir(inspect_this_thing)
      to_see2 = inspect_this_thing.some_attribute
      raise ValueError("Debugging")
    ...

    当您在Django的某些部分工作,这些部分没有很好的文档记录时,这尤其有用(Form.Changed_字段是我最近使用的字段)。

    ()

    不要为模板上下文写出每个变量,而是使用python builtin locals()命令,该命令为您创建一个字典:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #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))

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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()

    它在所有已安装的应用程序中检测app_settings.py。它不会导入,而是读取app_设置文件的内容并以内联方式执行。如果直接导入app_设置,将引发所有类型的django导入错误(因为django尚未初始化)。

    所以我的app/app_settings.py将如下所示:

    1
    2
    3
    MIDDLEWARE_CLASSES += (
        'app.middleware.FancyMiddleware',
    )

    现在只需将应用程序添加到已安装的应用程序中,而不必查找所有应用程序设置并将它们添加到settings.py(中间件、URL…)

    注意:如果django有一个附加额外设置的钩子,那么最好在启动时(或运行时)添加应用程序设置。