受问题系列“...的隐藏功能”的启发,我很想知道您最喜欢的 Django 技巧或您知道的鲜为人知但有用的功能。
- 请每个答案只包含一个提示。
- 如果有,请添加 Django 版本要求。
受问题系列“...的隐藏功能”的启发,我很想知道您最喜欢的 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 From the Ground Up ”中得到了这个提示。
安装Django 命令扩展和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(例如重定向)将使装饰器短路并按预期工作。
There's a set of custom tags I use all over my site's templates. Looking for a way to autoload it (DRY, remember?), I found the following:
from django import template
template.add_to_builtins('project.app.templatetags.custom_tag_module')
If you put this in a module that's loaded by default (your main urlconf for instance), you'll have the tags and filters from your custom tag module available in any template, without using {% load custom_tag_module %}
.
The argument passed to template.add_to_builtins()
can be any module path; your custom tag module doesn't have to live in a specific application. For example, it can also be a module in your project's root directory (eg. 'project.custom_tag_module'
).
Virtualenv + Python = life saver if you are working on multiple Django projects and there is a possibility that they all don't depend on the same version of Django/an application.
不要对您的 URL 进行硬编码!
改用url 名称,以及reverse
获取 URL 本身的函数。
定义 URL 映射时,为 URL 命名。
urlpatterns += ('project.application.views'
url( r'^something/$', 'view_function', name="url-name" ),
....
)
确保每个 URL 的名称都是唯一的。
我通常有一个一致的格式“project-appplication-view”,例如“cbx-forum-thread”用于线程视图。
更新(无耻地窃取ayaz的补充):
此名称可以在带有url
标签的模板中使用。
使用django 调试工具栏。例如,它允许查看在呈现视图时执行的所有 SQL 查询,您还可以查看其中任何一个的堆栈跟踪。
不要编写自己的登录页面。如果您使用的是 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
自动包含密钥。
几个月前我写了一篇关于这个的博客文章,所以我只是要剪切和粘贴:
开箱即用的 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)
因此,您想以某种方式通知我们发布新帖子的众多博客 ping 服务之一,重建最近的帖子缓存,并发布关于它的推文。有了信号,您就可以完成所有这些操作,而无需向 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 模型并在保存后执行它。
刚开始的时候不知道有Paginator,请确保你知道它的存在!!
使用IPython在任何级别跳转到您的代码并使用 IPython 的强大功能进行调试。安装 IPython 后,只需将此代码放在要调试的任何位置:
from IPython.Shell import IPShellEmbed; IPShellEmbed()()
然后,刷新页面,转到您的 runserver 窗口,您将进入一个交互式 IPython 窗口。
我在 TextMate 中设置了一个片段,所以我只需输入 ipshell 并点击选项卡。没有它我活不下去。
运行一个开发 SMTP 服务器,它只会输出发送给它的任何内容(如果您不想在开发服务器上实际安装 SMTP。)
命令行:
python -m smtpd -n -c DebuggingServer localhost:1025
如果您使用 Bash shell,请考虑安装 Django bash 完成脚本,该脚本extras/django_bash_completion
位于 Django 发行版中。django-admin.py
它支持和命令的制表符补全manage.py
,例如,您可以...
django-admin.py
。sql
,然后键入 [TAB] 以查看名称以 开头的所有可用选项sql
。django_extensions./manage.py runserver_plus
附带的功能真的很棒。
它创建了一个增强的调试页面,除其他外,使用 Werkzeug 调试器为堆栈中的每个点创建交互式调试控制台(见屏幕截图)。它还提供了一种非常有用的便捷调试方法dump()
,用于显示有关对象/框架的信息。
要安装,您可以使用 pip:
pip install django_extensions
pip install Werkzeug
然后添加'django_extensions'
到您的INSTALLED_APPS
元组中settings.py
并使用新扩展启动开发服务器:
./manage.py runserver_plus
这将改变您的调试方式。
我喜欢使用 Python 调试器 pdb 来调试 Django 项目。
这是学习如何使用它的有用链接:http ://www.ferg.org/papers/debugging_in_python.html
When trying to exchange data between Django and another application, request.raw_post_data
is a good friend. Use it to receive and custom-process, say, XML data.
Documentation: http://docs.djangoproject.com/en/dev/ref/request-response/
将Jinja2与 Django 一起使用。
如果您发现 Django 模板语言非常受限制(像我一样!),那么您不必拘泥于它。Django 很灵活,模板语言与系统的其余部分松散耦合,因此只需插入另一种模板语言并使用它来呈现您的 http 响应!
我使用Jinja2,它几乎就像 django 模板语言的增强版,它使用相同的语法,并允许您在 if 语句中使用表达式!不再制作自定义 if 标记,例如if_item_in_list
! 你可以简单地说%{ if item in list %}
,或{% if object.field < 10 %}
。
但这还不是全部;它有更多的功能来简化模板的创建,我在这里不能一一列举。
添加assert False
您的视图代码以转储调试信息。
这增加了上面关于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>
由于 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),
)
而不是使用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}
)
我没有足够的声誉来回复有问题的评论,但重要的是要注意,如果您要使用Jinja,它不支持模板块名称中的“-”字符,而 Django 支持。这给我带来了很多问题,并浪费了时间试图追踪它生成的非常模糊的错误消息。
每个人都知道有一个可以使用“manage.py runserver”运行的开发服务器,但是你知道还有一个用于提供静态文件(CSS / JS / IMG)的开发视图吗?
新手总是很困惑,因为 Django 并没有提供任何方法来提供静态文件。这是因为开发团队认为这是一个真实的 Web 服务器的工作。
但是在开发的时候,你可能不想设置Apache + mod_wisgi,它很重。然后您可以将以下内容添加到 urls.py:
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': '/path/to/media'}),
您的 CSS / JS / IMG 将在 www.yoursite.com/site_media/ 上提供。
当然,不要在生产环境中使用它。
django.db.models.get_model
确实允许您在不导入模型的情况下检索模型。
James 展示了它的便利性:“Django 技巧:编写更好的模板标签 — 迭代 4”。
开始设计您的网站时,网页设计应用程序非常有用。导入后,您可以添加它以生成示例文本:
{% load webdesign %}
{% lorem 5 p %}
I learned this one from the documentation for the sorl-thumbnails app. You can use the "as" keyword in template tags to use the results of the call elsewhere in your template.
For example:
{% url image-processor uid as img_src %}
<img src="{% thumbnail img_src 100x100 %}"/>
This is mentioned in passing in the Django templatetag documentation, but in reference to loops only. They don't call out that you can use this elsewhere (anywhere?) as well.
PyCharm IDE是一个很好的编码环境,尤其是调试环境,内置对 Django 的支持。
django.views.generic.list_detail.object_list -- 它为分页提供了所有的逻辑和模板变量(其中之一是我现在写的苦差事)。 包装它允许您需要任何逻辑。这个 gem 为我节省了很多小时在“搜索结果”页面中逐个调试错误,并使视图代码在此过程中更清晰。
使用数据库迁移。使用南。
使用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'
它还可以处理关系和集合。我们每天都在大量使用的生产代码中使用它,所以即使它是测试版,它也非常有用。它还有一组很好的存根,您可以在测试中使用它们。
(免责声明:虽然我不是这个库的作者,但我现在是一名提交者,做了一些小提交)
刚刚找到这个链接: http: //lincolnloop.com/django-best-practices/#table-of-contents - “Django Best Practices”。
无需评估整个查询集以检查您是否返回任何结果,而是在 Django 1.2+ 中使用 .exists() 并在以前的版本中使用 .count() 。
exists() 和 count() 都清除 order by 子句并从 DB 中检索单个整数。但是,exists() 将始终返回 1,因为 count 可能会返回更高的值,手动应用限制。exists() 中使用的has_result的来源和 count() 中使用的get_count的来源。
由于它们都返回一个整数,因此没有模型实例化,在内存中加载模型属性,也没有在您的数据库和应用程序之间传递大型 TextField。
如果您已经评估了查询,.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
如果您对模型进行更改
./manage.py dumpdata appname > appname_data.json
./manage.py reset appname
django-admin.py loaddata appname_data.json
使用信号即时添加访问器方法。
我在django-photologue中看到了这种技术:对于任何添加的 Size 对象,post_init 信号都会将相应的方法添加到 Image 模型中。如果添加站点巨人,则以巨人分辨率检索图片的方法将是image.get_giant_url()
。
这些方法是通过add_accessor_methods
从post_init
信号调用生成的:
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 站点中所做的一件事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
,但我还没有研究过。
我做的另一件事是使用单独的用户来执行数据库管理任务而不是其他所有任务。在我的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
其中 config in/etc/django/db_regular.py
是针对只能通过 SELECT、INSERT、UPDATE 和 DELETE 访问 Django 数据库/etc/django/db_admin.py
的用户,并且是针对具有这些权限以及 CREATE、DROP、INDEX、ALTER 和 LOCK TABLES 的用户。(migrate
命令来自South。)这为我提供了一些保护,防止 Django 代码在运行时与我的架构发生混淆,并且限制了 SQL 注入攻击可能造成的损害(尽管您仍然应该检查和过滤所有用户输入)。
(复制自我对另一个问题的回答)
不要在本地主机上运行 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 上的其他机器访问您的开发站点进行测试。
尽管开发服务器很小且相对安全,但请确保您受到防火墙的保护。
Django 调试工具栏真的很棒。不是真正的工具栏,它实际上会打开一个侧窗格,告诉您有关您正在查看的页面的各种信息 - 数据库查询、发送到模板的上下文变量、信号等等。
在自定义视图装饰器中使用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
注意__call__
:如果作者没有定义__name__
属性,则不适用于基于类的视图(具有方法定义的视图)。作为一种解决方法,请使用:
from django.utils.decorators import available_attrs
...
@wraps(fun, assigned=available_attrs(fun))
使用“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://codepatter.com/2009/04/10/how-to-add-locations-to-python-path-for-reusable-django-apps/看到了这个
通过 django 模板而不是 as_(ul|table|p)() 呈现表单。
本文展示了如何使用模板来呈现 CusstomForms 而不是as_p()
, as_table()
...
为了让它工作改变
from django import newforms as forms
至 from django import forms
from django.newforms.forms import BoundField
至 from django.forms.forms import BoundField
使用djangorecipe管理您的项目
您需要做的就是开始:
创建一个包含以下内容的 buildout.cfg:
[buildout]
parts=django
[django]
recipe=djangorecipe
version=1.1.1
project=my_new_site
settings=development
python bootstrap.py
(或者python bootstrap_dev.py
如果你想使用分发)。./bin/buildout
而已。您现在应该有一个新文件夹“my_new_site”,这是您的新 django 1.1.1 项目,并且在 ./bin 中,您将找到在django
正常安装中替换 manage.py 的 -script。
有什么好处?假设您想在项目中使用 django-comment-spamfighter 之类的东西。您所要做的就是将您的 buildout.cfg 更改为以下内容:
[buildout]
parts=django
[django]
recipe=djangorecipe
version=1.1.1
project=my_new_site
settings=development
eggs=
django-comments-spamfighter==0.4
请注意,我所做的只是添加最后两行,即 django-part 还应该具有 0.4 版中的 django-comments-spamfighter 包。下次运行时./bin/buildout
,buildout 将下载该包并修改 ./bin/django 以将其添加到其 PYTHONPATH。
djangorecipe 也适合使用 mod_wsgi 部署您的项目。只需将wsgi=true
设置添加到 buildout.cfg 的 django 部分,“django.wsgi”就会出现在 ./bin 文件夹中:-)
如果您将test
选项设置为应用程序列表,djangorecipe 将为您创建一个很好的包装器,为您的项目中列出的应用程序运行所有测试。
如果您想在独立环境中开发单个应用程序以进行调试等,Jakob Kaplan-Moss 在他的博客上有一个非常完整的教程
在生产环境中自动设置“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/
在你的 urlconf 中使用 reverse。
这是我不明白为什么它不是默认设置的那些技巧之一。
这是我拿起它的链接:http: //andr.in/2009/11/21/calling-reverse-in-django/
这是代码片段:
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') )
这是一种非常简单的方法,无需在 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 文件中以节省时间。
在初始化时更改 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 片段
django_extensions
来自https://github.com/django-extensions/django-extensions很棒。
几个不错的./manage.py
命令:
shell_plus
- 从所有 INSTALLED_APPS 中自动导入模型show_urls
- 打印项目中所有应用程序中定义的所有 urlrunscript
- 在项目上下文中运行任何脚本(您可以使用模型和其他与 Django 相关的模块)派对有点晚了。但是 Django Canvas 最近出现了,它值得在这里占有一席之地。
不要以django-admin.py startproject
. 相反,您可以使用Django Canvas之类的东西来帮助将空白项目与您需要的模块拼凑在一起。
你去那个网站,勾选一些选项,然后下载一个空白项目,就这么简单。
它具有所有常见的东西,例如 South 模式迁移和命令扩展,以及这里提到的许多其他最佳实践。此外,它还有一个很棒的start.sh/shart.bat
脚本,可以安装 python、virtualenv、pip、django 以及从 Windows、osx 或 linux 的新副本开始所需的任何东西。
使用isapi-wsgi和django-pyodbc在 Windows 上使用 IIS 和 SQL Server 运行 Django!
如果您还没有阅读Unbreak Django ,请阅读。它包含许多有关 django 陷阱的有用信息。
为具有相同结构的旧表集创建动态模型:
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()
。
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 没有应用设置,所以我做了自己的 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(中间件、urls...)
注意:如果 Django 有一个附加额外设置的钩子会更好,这样可以在启动时(或在运行时)添加应用程序设置。
dir() & raise ValueError()
为了在开发过程中调试/探索事物的状态,我使用了以下技巧:
...
to_see = dir(inspect_this_thing)
to_see2 = inspect_this_thing.some_attribute
raise ValueError("Debugging")
...
当您处理 django 中没有特别详细记录的部分时,这尤其有用(form.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))