django

时间:2015-04-28 08:31:55

标签: django django-views url-routing

我有一个RoutingUrl模型,它描述了我的网站上使用的所有网址以及视图(View模型的外键),它必须管理网址和其他一些路由信息。网址的大小不断增加,也应该支持重定向。模型或多或少如下:

class RoutingUrl(models.Model):
    url = models.CharField(unique=True, verbose_name='routing url')
    crc_checksum = models.IntegerField(editable=False)
    redirect_to = models.ForeignKey('RoutingUrl', related_name='redirect_from', blank=True, null=True)
    view = models.ForeignKey(View, related_name='routing_urls')

    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

class View(models.Model):
    name = models.CharField()

RoutingUrl还有一个通用外键,模型包含有关要呈现的页面的信息(必须支持不同的模型,这就是通用外键的原因)。

现在的问题是:如何实现这样的动态路由到django?我的感觉是我有两种选择:

  1. 我可以创建一个中间件,它将通过实现process_request方法(在检查urlpatterns之前)将请求分派给正确的视图。显然,这样的中间件应该位于中间件堆栈的底部,以便维护其他中间件的功能。因此,该解决方案将绕过Django路由系统。
  2. 另一种选择可能是添加一个匹配所有匹配的单个catch所有urlpattern,然后只编写我自己的处理程序/调度程序作为视图。该处理程序实现了路由进程,因此将调用适当的视图并返回其HttpResponse
  3. 你能否告诉我两种选择中哪一种最适合实施这样的路由?当然,如果有第三个更好的选择,请不要犹豫向我推荐。

1 个答案:

答案 0 :(得分:1)

调查django中间件钩子,很明显process_request不是实现路由功能的最佳候选者。的确,从文档中可以看出:

  

它应该返回None或HttpResponse对象。如果它返回   没有,Django将继续处理此请求,执行任何请求   其他process_request()中间件,然后是process_view()中间件,   最后,适当的观点。 如果它返回HttpResponse   对象,Django不会打扰任何其他请求,视图或   异常中间件或适当的视图;它会应用响应   中间件到那个HttpResponse,并返回结果。

因此,HttpResponse将破坏中间件堆栈功能。 process_view或多或少相同,这将避免异常中间件的调用。在这一点上,采用第二种选择似乎更聪明......

django-cms插件证实了这种直觉,正如您从urlpatterns定义的source code中看到的那样:

from django.conf import settings
from django.conf.urls import url

from cms.apphook_pool import apphook_pool
from cms.appresolver import get_app_patterns
from cms.views import details

# This is a constant, really, but must live here due to import order
SLUG_REGEXP = '[0-9A-Za-z-_.//]+'

if settings.APPEND_SLASH:
    regexp = r'^(?P<slug>%s)/$' % SLUG_REGEXP
else:
    regexp = r'^(?P<slug>%s)$' % SLUG_REGEXP

if apphook_pool.get_apphooks():
    # If there are some application urls, use special resolver,
    # so we will have standard reverse support.
    urlpatterns = get_app_patterns()
else:
    urlpatterns = []

urlpatterns.extend([
    url(regexp, details, name='pages-details-by-slug'),
    url(r'^$', details, {'slug': ''}, name='pages-root'),
])