路由

Channels 中的路由是使用一個較 Django 核心簡單的系統來達成的。給予一個所有可能路由的序列,Channels 將會遍歷所有的可能直到發現一個相符的路由,然後該路由的 consumer 將會被執行。

The difference comes, however, in the fact that Channels has to route based on more than just URL; channel name is the main thing routed on, and URL path is one of many other optional things you can route on, depending on the protocol (for example, imagine email consumers - they would route on domain or recipient address instead).

The routing Channels takes is just a list of routing objects - the three built in ones are route, route_class and include, but any object that implements the routing interface will work:

  • A method called match, taking a single message as an argument and returning None for no match or a tuple of (consumer, kwargs) if matched.
  • 有個功能鍵叫”channel_names”可回覆一組可搭配的 channel 名稱,這使 channel 層可以管控他們

以下是三個預設的路由物件:

  • route: Takes a channel name, a consumer function, and optional filter keyword arguments.
  • route_class: Takes a class-based consumer, and optional filter keyword arguments. Channel names are taken from the consumer’s channel_names() method.
  • include: Takes either a list or string import path to a routing list, and optional filter keyword arguments.

篩選器

Filtering is how you limit matches based on, for example, URLs; you use regular expressions, like so:

route("websocket.connect", consumers.ws_connect, path=r"^/chat/$")

備註

和Django內建的URL Routing不同。在Django內建的Routing裡,第一個/會被略去,已求簡潔。然而在Channels中,第一個/是被保留的。這是因為Routing是通用的,且不是只為了URL所設計。

你可以使用多重過濾器:

route("email.receive", comment_response, to_address=r".*@example.com$", subject="^reply")

Multiple filters are always combined with logical AND; that is, you need to match every filter to have the consumer called.

Filters can capture keyword arguments to be passed to your function or your class based consumer methods as a kwarg:

route("websocket.connect", connect_blog, path=r'^/liveblog/(?P<slug>[^/]+)/stream/$')

你也可以指定過濾”include”:

include("blog_includes", path=r'^/liveblog')

When you specify filters on include, the matched portion of the attribute is removed for matches inside the include; for example, this arrangement matches URLs like /liveblog/stream/, because the outside include strips off the /liveblog part it matches before passing it inside:

inner_routes = [
    route("websocket.connect", connect_blog, path=r'^/stream/'),
]

routing = [
    include(inner_routes, path=r'^/liveblog')
]

You can also include named capture groups in the filters on an include and they’ll be passed to the consumer just like those on route; note, though, that if the keyword argument names from the include and the route clash, the values from route will take precedence.