Package: bokeh-django
bokeh-djangoSupport for running Bokeh apps with DjangoIntroductionBoth Bokeh and Django are web frameworks that can be used independently to build and host web applications. They each have their own strengths and the purpose of thebokeh_djangopackage is to integrate these two frameworks so their strengths can be used together.Installationpip install bokeh-djangoConfigurationThis documentation assumes that you have already started aDjango project.bokeh-djangoenables you to define routes (URLs) in your Django project that will map to Bokeh applications or embed Bokeh applications into a template rendered by Django. However, before defining the routes there are several configuration steps that need to be completed first.ConfigureINSTALLED_APPS:In thesettings.pyfile ensure that bothchannelsandbokeh_djangoare added to theINSTALLED_APPSlist:INSTALLED_APPS=[...,'channels','bokeh_django',]Set Up an ASGI Application:By default, the Django project will be configured to use a WSGI application, but thestartprojectcommand should have also created anasgi.pyfile.Insettings.pychange theWSGI_APPLICATIONsetting toASGI_APPLICATIONand modify the path accordingly. It should look something like this:ASGI_APPLICATION='mysite.asgi.application'Next, modify the contents of theasgi.pyfile to get the URL patterns from thebokeh_djangoapp config. Something similar to this will work:fromchannels.authimportAuthMiddlewareStackfromchannels.routingimportProtocolTypeRouter,URLRouterfromdjango.appsimportappsbokeh_app_config=apps.get_app_config('bokeh_django')application=ProtocolTypeRouter({'websocket':AuthMiddlewareStack(URLRouter(bokeh_app_config.routes.get_websocket_urlpatterns())),'http':AuthMiddlewareStack(URLRouter(bokeh_app_config.routes.get_http_urlpatterns())),})Configure Static Files:Both Bokeh and Django have several ways of configuring serving static resources. This documentation will describe several possible configuration approaches.The Bokehresourcessettingcan be set to one of several values (e.gserver,inline,cdn), the default iscdn. If this setting is set toinline, orcdnthen Bokeh resources will be served independently of Django resources. However, if the Bokehresourcessetting is set toserver, then the Bokeh resources are served up by the Django server in the same way that the Django static resources are and so Django must be configured to be able to find the Bokeh resources.To specify the Bokehresourcessetting add the following to the Djangosettings.pyfile:frombokeh.settingsimportsettingsasbokeh_settingsbokeh_settings.resources='server'If the Bokehresourcessetting is set toserverthen we must add the location of the Bokeh resources to theSTATICFILES_DIRSsetting:frombokeh.settingsimportsettingsasbokeh_settings,bokehjsdirSTATICFILES_DIRS=[...,bokehjsdir(),]Django can be configured to automatically find and collect static files using thestaticfilesapp, or the static file URL patterns can be explicitly added to the list ofurlpatternsin theurls.pyfile.To explicitly add the static fileurlpatternsadd the following to theurls.pyfile:fromdjango.contrib.staticfiles.urlsimportstaticfiles_urlpatternsfrombokeh_djangoimportstatic_extensionsurlpatterns=[...,*static_extensions(),*staticfiles_urlpatterns(),]Be sure that thestatic_extensionsare listed before thestaticfiles_urlpatterns.Alternatively, you can configure thestaticfilesappby adding'django.contrib.staticfiles',toINSTALLED_APPS:INSTALLED_APPS=[...,'django.contrib.staticfiles','channels','bokeh_django',]Next addbokeh_django.static.BokehExtensionFinderto theSTATICFILES_FINDERSsetting. The default value forSTATICFILES_FINDERShas two items. If you override the default by adding theSTATICFILES_FINDERSsetting to yoursettings.pyfile, then be sure to also list the two default values in addition to theBokehExtensionFinder:STATICFILES_FINDERS=("django.contrib.staticfiles.finders.FileSystemFinder","django.contrib.staticfiles.finders.AppDirectoriesFinder",'bokeh_django.static.BokehExtensionFinder',)Define RoutesBokeh applications are integrated into Django through routing or URLs.In a Django app, the file specified by theROOT_URLCONFsetting (e.g.urls.py) must defineurlpatternswhich is a sequence ofdjango.url.pathand/ordjango.url.re_pathobjects. When integrating a Django app with Bokeh, theurls.pyfile must also definebokeh_appsas a sequence ofbokeh_djangorouting objects. This should be done using thebokeh_djagno.documentand/orbokeh_django.autoloadfunctions.DocumentThe first way to define a route is to usebokeh_django.document, which defines a route to a Bokeh app (as either a file-path or a function).frombokeh_djangoimportdocumentfrom.viewsimportmy_bokeh_app_functionbokeh_apps=[document('url-pattern/','/path/to/bokeh/app.py'),document('another-url-pattern/',my_bokeh_app_function)]When using thedocumentroute Django will route the URL directly to the Bokeh app and all the rendering will be handled by Bokeh.DirectoryAn alternative way to createdocumentroutes is to usebokeh_django.directoryto automatically create adocumentroute for all the bokeh apps found in a directory. In this case the file name will be used as the URL pattern.frombokeh_djangoimportdirectorybokeh_apps=directory('/path/to/bokeh/apps/')AutoloadTo integrate more fully into a Django application routes can be created usingautoload. This allows the Bokeh application to be embedded in a template that is rendered by Django. This has the advantage of being able to leverage Django capabilities in the view and the template, but is slightly more involved to set up. There are five components that all need to be configured to work together: theBokeh handler, theDjango view, thetemplate, theDjango URL path, and theBokeh URL route.Bokeh HandlerThe handler is a function (or any callable) that accepts abokeh.document.Documentobject and configures it with the Bokeh content that should be embedded. This is done by adding a Bokeh object as the document root:frombokeh.documentimportDocumentfrombokeh.layoutsimportcolumnfrombokeh.modelsimportSliderdefbokeh_handler(doc:Document)->None:slider=Slider(start=0,end=30,value=0,step=1,title="Example")doc.add_root(column(slider))The handler can also embed a Panel object. In this case the document is passed in to theserver_docmethod of the Panel object:importpanelaspndefpanel_handler(doc:Document)->None:pn.Row().server_doc(doc)Django ViewThe view is a Django function that accepts arequestobject and returns aresponse. A view that embeds a Bokeh app must create abokeh.embed.server_documentand pass it in the context to the template when rendering the response.frombokeh.embedimportserver_documentfromdjango.shortcutsimportrenderdefview_function(request):script=server_document(request.build_absolute_uri())returnrender(request,"embed.html",dict(script=script))TemplateThe template document is a Django HTML template (e.g."embed.html") that will be rendered by Django. It can be as complex as desired, but at the very least must render thescriptthat was passed in from the context:<!doctype html><htmllang="en"><body>{{ script|safe }}</body></html>Django URL PathTheDjango URL Pathis adjango.url.pathordjango.url.re_pathobject that is included in theurlpatterssequence and that maps a URL pattern to theDjango Viewas would normally be done with Django.urlpatterns=[path("embedded-bokeh-app/",views.view_function),]Bokeh URL RouteTheBokeh URL Routeis abokeh_django.autoloadobject that is included in thebokeh_appssequence and that maps a URL pattern to theBokeh handler.frombokeh_djangoimportautoloadbokeh_apps=[autoload("embedded-bokeh-app/",views.handler)]Note that the URL pattern should be the same URL pattern that was used in the correspondingDjango URL Path. In reality the URL pattern must match the URL that theserver_documentscript is configured with in theDjango View. Normally, it is easiest to use the URL from therequestobject (e.g.script = server_document(request.build_absolute_uri())), which is the URL of the correspondingDjango URL Path.