向 Django 添加更多 CoC
我来自 Cake 背景,现在刚刚开始学习 Django。我非常喜欢它,但我有点希望它像蛋糕一样使用约定优于配置。那么,
如何自动获取 Cake 样式的 URL?例如,如果我访问
mysite.com/posts/view/5
,它将加载mysite.posts.views.view
并传递参数5< /代码> 到了吗?我想我可以在 urls.py 中添加类似
(r'^(.*)/(.*)', 'mysite.$1.$2'),
的内容,但当然,这赢了不起作用。如何自动加载模板?每个视图函数都应该自动加载一个模板,例如
templates/posts/view.html
。
这是否可能,或者我是否必须破解 Django 的核心?
这是我的解决方案,基于 Carl 建议:
urlpatterns = patterns('',
# url pats here
url(r'^(?P<app>\w+)/(?P<view>\w+)/(?P<args>.*)$', 'urls.dispatch')
)
def dispatch(req, app, view, args): # FIXME: ignores decorators on view func!
func = get_callable(app+'.views.'+view)
if args:
ret = func(req, *args.split('/'))
else:
ret = func(req)
if type(ret) is dict:
return render_to_response(app+'/'+view+'.html', ret)
else:
return ret
似乎有效初步测试效果很好。使用单个函数解决这两个问题。不过可能不支持 GET 风格的参数。
I come from a Cake background, and I'm just starting to learn Django now. I'm liking it quite a bit, but I kinda wish it used convention over configuration like cake does. So,
How can I get Cake-style URLs automatically? For example, if I went to
mysite.com/posts/view/5
it would load upmysite.posts.views.view
and pass an argument5
to it? I was thinking I could add something like(r'^(.*)/(.*)', 'mysite.$1.$2'),
to urls.py, but of course, that won't work.How can I automatically load up a template? Each view function should automatically load a template like
templates/posts/view.html
.
Is this even possible, or do I have to hack the core of Django?
Here's my solution, based on what Carl suggested:
urlpatterns = patterns('',
# url pats here
url(r'^(?P<app>\w+)/(?P<view>\w+)/(?P<args>.*)
Seems to be working pretty well with initial tests. Solves both problems with a single function. Probably won't support GET-style arguments tho.
, 'urls.dispatch')
)
def dispatch(req, app, view, args): # FIXME: ignores decorators on view func!
func = get_callable(app+'.views.'+view)
if args:
ret = func(req, *args.split('/'))
else:
ret = func(req)
if type(ret) is dict:
return render_to_response(app+'/'+view+'.html', ret)
else:
return ret
Seems to be working pretty well with initial tests. Solves both problems with a single function. Probably won't support GET-style arguments tho.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这些要点都可以在不破解 Django 核心的情况下实现,但其中任何一个都需要对高级 Python 技术有一定程度的熟悉。
您可以使用如下模式执行通用 URL 模式:
然后定义一个“myresolverfunc”“view”函数,该函数采用“appname”、“viewfunc”和“args”参数,并实现您想要的任何逻辑,将 args 拆分为“ /”并动态导入和分派到引用的任何视图函数。最棘手的部分是动态导入,您可以在 Django 源代码中搜索“importlib”来查看动态导入在内部各个地方是如何完成的。
自动模板加载器可以实现为视图函数装饰器,类似于各种 "render_to" 装饰器 在那里,除了您将生成模板名称而不是将其传递给装饰器。您必须内省函数对象才能获取其名称。获取应用程序名称会比较棘手;您可能只想将其硬编码为每个views.py 文件中的模块级全局变量,或者与上面的URL 调度程序结合使用,并让它使用应用程序名称等注释请求对象。
Those points are both implementable without hacking Django core, but either one will require a non-trivial level of familiarity with advanced Python techniques.
You can do the generic URL pattern with a pattern like this:
Then define a 'myresolverfunc' "view" function that takes "appname", "viewfunc", and "args" parameters, and implement whatever logic you want, splitting args on "/" and dynamically importing and dispatching to whatever view function is referenced. The trickiest part is the dynamic import, you can search Django's source for "importlib" to see how dynamic imports are done internally various places.
The automatic template loader can be implemented as a view function decorator similar to the various "render_to" decorators out there, except you'll generate the template name rather than passing it in to the decorator. You'll have to introspect the function object to get its name. Getting the app name will be trickier; you'll probably just want to hardcode it as a module-level global in each views.py file, or else work in conjunction with the above URL dispatcher, and have it annotate the request object with the app name or some such.
我不认为你需要为此破解 Django 的核心。听起来您可能需要通用视图。另请查看通用视图主题指南。
通用视图文档中给出的第一个示例听起来像是您的第一个要点:
, 'direct_to_template', {'template':'foo_index.html'}), (r'^foo/(?P\d+)/
... 对 /foo/ 的请求将呈现模板 foo_index.html,对 /foo/15/ 的请求将呈现 foo_detail.html,其中上下文变量 {{ params.id }} 设置为15.
, 'direct_to_template', {'template':'foo_detail.html'}), )... 对 /foo/ 的请求将呈现模板 foo_index.html,对 /foo/15/ 的请求将呈现 foo_detail.html,其中上下文变量 {{ params.id }} 设置为15.
I don't you'll need to hack the core of Django for this. It sounds like you might be in need of generic views. Also check out the Generic Views topic guide.
The first example given in the generic views documentation sounds like your first bullet point:
, 'direct_to_template', {'template':'foo_index.html'}), (r'^foo/(?P<id>\d+)/
... a request to /foo/ would render the template foo_index.html, and a request to /foo/15/ would render the foo_detail.html with a context variable {{ params.id }} that is set to 15.
, 'direct_to_template', {'template':'foo_detail.html'}), )... a request to /foo/ would render the template foo_index.html, and a request to /foo/15/ would render the foo_detail.html with a context variable {{ params.id }} that is set to 15.