2015-04-28 69 views
1

我有一個RoutingUrl模型,該模型描述了我的站點上使用的所有url以及必須管理url和其他一些路由信息的視圖(View模型的外鍵)。這些網址的規模不斷擴大,並且還應該支持重定向。這些模型都或多或少如下:django中的動態url路由

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方法(因此是檢查URL模式之前)調度請求到右視圖的照顧。顯然這樣的中間件應該放置在中間件堆棧的底部,以便維護其他中間件的功能。這個解決方案將繞過Django路由系統。
  2. 另一種選擇可能是添加一個匹配所有內容的單個catch全部urlpattern,然後將我自己的處理程序/調度程序作爲視圖編寫。該處理程序實現路由過程,因此將調用相應的視圖並返回其HttpResponse

你能建議我哪兩個選項是最好的實現這樣的路由?當然,如果有第三種更好的選擇,不要猶豫,向我建議。

回答

0

調查了一下django中間件鉤子,很明顯process_request並不是實現路由功能的最佳選擇。事實上,從文檔:

它應該返回無或HttpResponse對象。如果它返回 無,Django將繼續處理此請求,執行任何其他process_request()中間件,然後執行任何 process_view()中間件, ,最後是適當的視圖。 如果它返回一個HttpResponse 對象,Django不會打擾任何其他請求,查看或 異常中間件或相應的視圖;它會將響應 中間件應用到該HttpResponse,並返回結果。

因此,HttpResponse會打破中間件堆棧功能。 process_view或多或少都是一樣的,這將避免異常中間件的調用。在這一點上似乎更聰明地採取第二個選項...

Django的-CMS插件證實了這一直覺,因爲你可以從URL模式定義的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'), 
])