I'm currently trying out bokeh server to serve some interactive bokeh charts to my django app, but having difficulty connecting via views.py.
The browser returns an OSError:
Cannot pull session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)
The server itself returns 404 error for the request:
200-03-31 08:17:09,179 404 GET /ws?bokeh-protocol-version=1.0&bokeh-session-id=ZhGn4XcmC1qDPYtF4SRPGPa1GzSgTqktqmvkIEGJke26 (127.0.0.1) 0.55ms
My server is set up as follows:
bokeh_server
|
|--main.py
main.py is a very basic bokeh chart
main.py
from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.plotting import figure
from bokeh.models.sources import ColumnDataSource
source = ColumnDataSource(dict(x=list(range(5)), y=list(range(5))))
p = figure(width=300, height=300, tools=[], toolbar_location=None, name="test")
p.line(x='x', y='y', source=source)
curdoc().add_root(column(p, sizing_mode='scale_width'))
Running the server (bokeh serve bokeh_server) and then opening https://localhost:5006 in a browser renders the chart correctly (https://localhost:5006/bokeh_server)
The issue comes when I try to open it from my django app.
views.py
from django.shortcuts import render
from django.http import HttpResponse
from bokeh.client import pull_session
def testbserver(request):
session = pull_session(url="http://localhost:5006/")
script = server_session(model=None,
session_id=None,
url="http://localhost:5006/",
)
return render(request, 'testserver.html', {'script':script})
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('testbserver/', views.testbserver, name='testbserver'),
]
testserver.html
{% extends "base_generic.html" %}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12">
{{script | safe }}
</div>
</div>
</div>
{% endblock %}
I've tried running the server with websockets allowed (bokeh serve bokeh_server/ --allow-websocket-origin="*" --log-level trace) but still get the same error.
Any suggestions for other things to try are gratefully received!
Thanks to #Eugene Pakhomov for the pointers, needed to update views.py to:
views.py
from django.shortcuts import render
from django.http import HttpResponse
from bokeh.client import pull_session
from bokeh.embed import server_session
def testbserver(request):
session = pull_session(url="http://localhost:5006/bokeh_server")
script = server_session(model=None,
session_id=session.id,
url="http://localhost:5006/bokeh_server",
)
return render(request, 'testserver.html', {'script':script})
There was also an issue in the testserver.html - I wasn't making the script safe:
testserver.html
{% extends "base_generic.html" %}
{% block content %}
<head>
<link href = "https://cdn.pydata.org./bokeh/release/bokeh-1.4.0.min.css" rel = "stylesheet" type = "text/css" >
<link href = "https://cdn.pydata.org./bokeh/release/bokeh-widgets-1.4.0.min.css" rel = "stylesheet" type = "text/css" >
<link href = "https://cdn.pydata.org./bokeh/release/bokeh-tables-1.4.0.min.css" rel = "stylesheet" type = "text/css" >
<script type = "text/javascript" src = "https://cdn.pydata.org./bokeh/release/bokeh-1.4.0.min.js"> </script>
<script type = "text/javascript" src = "https://cdn.pydata.org./bokeh/release/bokeh-widgets-1.4.0.min.js"> </script>
<script type = "text/javascript" src = "https://cdn.pydata.org./bokeh/release/bokeh-tables-1.4.0.min.js"> </script>
<h1>Test</h1>
{{script | safe}}
</head>
<div style="margin-left:20px;margin-top:20px">
<body>
{{div | safe}}
</body>
{% endblock %}
Related
This is a flask application which usually works.
My plots generated with bokeh are not showing up on the page at all. I can see that they are added to the html when I look with the tools but they're not visible. The page does not break and I can visit it as normal. I have tried everything from their page but now I just want the simplest example to work. When applied the json variant I just got a json printed on the page where the plot's supposed to be.
What have I missed?
EDIT: A minimum working example is also apreciated.
My route
from flask import Blueprint, render_template, redirect, url_for, flash
import json
from bokeh.embed import json_item, server_document, components
from bokeh.plotting import figure, curdoc
from bokeh.resources import CDN
from bokeh.sampledata.iris import flowers
from bokeh.layouts import gridplot
from bokeh.models import BoxSelectTool, LassoSelectTool
from bokeh.client import pull_session
test_bp = Blueprint(
'test_bp', __name__,
template_folder='templates',
static_folder='static'
)
#test_bp.route('/test_site', methods=['GET', 'POST'])
def test_site_view():
plot = figure()
plot.circle([1, 2], [3, 4])
script, div = components(plot)
return render_template(
'test.html',
script=script,
div=div
)
My test.html
{% extends "base.html" %}
<header>
{{ script|safe }}
</header>
{% block content %}
<h1>Plot</h1>
<div>
{{ div|safe }}
</div>
{% endblock %}
base.html includes
<head>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-2.1.0.min.js"
crossorigin="anonymous"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.1.0.min.js"
crossorigin="anonymous"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.1.0.min.js"
crossorigin="anonymous"></script>
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.1.0.min.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" />
</head>
For starters, you are trying to load CDN resources that don't actually exists. Bokeh stopped publishing separate CSS files at version 2.0. Since it is important that the CDN and Python versions match, it's best to just always let Bokeh itself format the necessary resources:
#test_bp.route('/test_site', methods=['GET', 'POST'])
def test_site_view():
plot = figure()
plot.circle([1, 2], [3, 4], size=40)
script, div = components(plot)
return render_template(
'test.html',
script=script,
div=div,
resources=CDN.render()
)
works with this template:
<head>
{{ resources|safe }}
</head>
<header>
{{ script|safe }}
</header>
{% block content %}
<h1>Plot</h1>
<div>
{{ div|safe }}
</div>
{% endblock %}
I am working on a project i python3 Django,
it will test your knowledge from road-signs in Slovakia.
A problem occurred when i stored all 300 signs images on Imgur.
If i open firstly just image with a sign and than image inside of my HTML page everything works just fine, but i need to generate random images so i dn't know which one will be next one. Console in google chrome gives me 403 error code 'forbidden' also i can see in network tab of developer tools that it loads the image as txt/plain, which seems suspicious to me.
Can you help me somehow please?
Here is my html
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static
'app_signs/style.css' %}">
</head>
<body class="question">
<form action="/question" method = "post">{% csrf_token %}
<div class="container">
<br>
<img src="{{ right_sign.signurl }}" class="main_sign" alt="FOTKA">
<br>
<h3>Aka je to znacka?</h3>
{% for sign in list%}
<p>{{ sign }}<p>
{% endfor %}
</div>
</form>
</body>
Here are views.py
from django.http import HttpResponse
from django.template import loader
from django.views.decorators.http import require_http_methods
from django.shortcuts import redirect
from app_signs.models import sign
import random
#require_http_methods(["GET", "POST"])
def question(request):
if request.method == 'GET':
rndint1 = '{:03}'.format(random.randint(1, 386))
rndint2 = '{:03}'.format(random.randint(1, 386))
rndint3 = '{:03}'.format(random.randint(1, 386))
rndint4 = '{:03}'.format(random.randint(1, 386))
right_sign = sign.objects.get(sign_id=rndint1)
fake_sign1 = sign.objects.get(sign_id=rndint2)
fake_sign2 = sign.objects.get(sign_id=rndint3)
fake_sign3 = sign.objects.get(sign_id=rndint4)
list_sign = [right_sign.sign_name,
fake_sign1.sign_name,
fake_sign2.sign_name,
fake_sign3.sign_name]
random.shuffle(list_sign, random.random)
template = loader.get_template('app_signs/question.html')
return HttpResponse(template.render({'right_sign': right_sign,
'list': list_sign}, request))
And here are models
from django.db import models
class sign(models.Model):
sign_category = models.CharField(max_length=250)
sign_id = models.CharField(max_length=4)
sign_name = models.CharField(max_length=250)
sign_url = models.CharField(max_length=250)
def __str__(self):
return self.sign_name
I finally found solution, it wasn't anything with python code. Trick was in changing 127.0.0.1 to localhost in url.
My question is similar to Same URL in multiple views in Django, but I am not rendering templates on the basis of user_authentication, but rather on the basis of JavaScript enabled or disabled in the browser.
What I am trying to do?
I am trying to render the index.html page if JavaScript is enabled in the browser, otherwise I want to render jsDisabled.html page if it's disabled and both of the pages should be rendered on the same URL pattern, for example:
localhost:8000 should either render index.html if JavaScript is enabled in the browser or it should render jsDisabled.html page if JavaScript is disabled.
Note: I am checking if JavaScript is disabled in the browser by using the <noscript> tag which will run when JavaScript is disabled.
Here is my code so far:
base.html:
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
</head>
<body class="noJs">
...
abc
...
<noscript>
<style type="text/css">
.noJs {
display: none;
}
</style>
<meta http-equiv="refresh" content="{% ulr 'index' 1 %}"> /* This should render jsDisabled.html page on the same URL which is 'localhost:8000' */
</noscript>
</body>
</html>
urls.py:
from django.conf.urls import include, url
from django.contrib import admin
from . import views
urlpatterns = [
...
url(r'^(?P<flag>[0-1])$', views.index, name='index'),
]
views.py:
from django.shortcuts import render
def index(request, flag):
if (flag):
return render(request, 'jsDisabled.html')
else:
return render(request, 'index.html')
Depending on your Django version you may need to specify TEMPLATE_DIR = in settings.py (in newer versions this isn't required).
Here is some helpful information on template and tag logic:
Main/templates/myapp/base.html
Main/templates/myapp/index.html
Main/templates/myapp/includes/yes_js.html
Main/templates/myapp/includes/no_js.html
base.html:
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
index.html:
{% extends 'myapp/base.html' %}
{% load staticfiles %}
{% block content %}
<noscript>
{% include 'no_js.html' %}
</noscript>
{% include 'yes_js.html' %}
{% endblock %}
After a lot of debugging I finally found the solution :) And here it is:
base.html:
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class="noJs">
...
abc
...
</div>
<noscript>
<style type="text/css">
.noJs {
display: none;
}
</style>
{% include 'includes/jsDisabled.html' %}
</noscript>
</body>
</html>
urls.py
from django.conf.urls import include, url
from django.contrib import admin
from . import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^articles/', include('articles.urls')),
url(r'^contact/', include('contact.urls')),
url(r'^temp/',views.temp, name="temp"),
url(r'^$', views.index, name='index'),
]
views.py:
from django.shortcuts import render
def index(request):
return render(request,'index.html')
def temp(request):
return render(request,'temp.html')
I included the include built-in template tag as {% include 'includes/jsDisabled.html' %} suggested by #noes1s by creating a folder named includes inside the templates folder and placing jsDisabled.html inside of it.
I'm trying to display a simple form input-text box with Django. I'm am deploying on Amazon AWS. The site works fine on a different server (pythonanywhere) but there is a major problem on AWS. Specifically, the input box is not being displayed. I'm using templates as follows:
home.html
{% extends 'lists/base.html' %}
{% block header_text %}Start a new To-Do list {% endblock %}
{% block form_action %}{% url 'new_list' %}{% endblock %}
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X UA-Compatible" content="IE-edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>To-Do lists</title>
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/base.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3 jumbotron">
<div class="text-center">
<h1>{% block header_text %}{% endblock %}</h1>
<form method="POST" action="{% block form_action %}{% endblock %}">
{{ form.text }}
{% csrf_token %}
{% if form.errors %}
<div class = "form-group has-error">
<span class = "help-block">{{ form.text.errors }}</span>
</div>
{% endif %}
</form>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-md-offset-3">
{% block table %}
{% endblock %}
</div>
</div>
</div>
</body>
</html>
models.py
from django.db import models
from django
.core.urlresolvers import reverse
class List(models.Model):
def get_absolute_url(self):
return reverse('view_list', args=[self.id])
# Create your models here.
class Item(models.Model):
text = models.TextField(default = '')
list = models.ForeignKey(List, default = None)
#list = models.ForeignKey(List , default=None)
forms.py
from django import forms
from lists.models import Item
EMPTY_ITEM_ERROR = "You can't have an empty list item"
class ItemForm(forms.models.ModelForm):
class Meta:
model = Item
fields = ('text',)
widgets ={
'text' : forms.fields.TextInput(attrs={
'placeholder': 'Enter a to-do item',
'class': 'form-control input-lg',
}),
}
error_messages = {
'text' : { 'required': EMPTY_ITEM_ERROR }
}
views.py
from django.shortcuts import redirect, render
from lists.models import Item, List
from django.core.exceptions import ValidationError
from lists.forms import ItemForm
from lists.models import Item, List
# Create your views here.
def home_page(request):
return render(request, 'lists/home.html', {'form': ItemForm()})
urls.py
from django.conf.urls import url
from lists import views
urlpatterns = [
url(r'^new$', views.new_list, name='new_list'),
url(r'^(\d+)/$', views.view_list, name='view_list'),
]
Currently the site displays the following:
However it should (and does on a different website) display this:
I've pushed/pulled the entire project to github and the code between each site is identical, yet I'm not seeing why the text input isn't displayed, unless the form needs to be initialized in Django somehow or a quirk to AWS?
When comparing the two sites, the one without the text-box does not generate the following:
<input class="form-control input-lg" id="id_text" name="text" placeholder="Enter a to-do item" type="text" />
Even though it should, per the base.html syntax.
Updated
The full views.py (per suggested comment) is:
from django.shortcuts import redirect, render
from lists.models import Item, List
from django.core.exceptions import ValidationError
from lists.forms import ItemForm
from lists.models import Item, List
# Create your views here.
def home_page(request):
return render(request, 'lists/home.html', {'form': ItemForm()})
def new_list(request):
form = ItemForm(data=request.POST)
if form.is_valid():
list_ = List.objects.create()
Item.objects.create(text=request.POST['text'], list=list_)
return redirect(list_)
else:
return render(request, 'lists/home.html', {"form": form})
def view_list(request, list_id):
list_ = List.objects.get(id=list_id)
form = ItemForm()
if request.method == 'POST':
form = ItemForm(data=request.POST)
if form.is_valid():
Item.objects.create(text=request.POST['text'], list=list_)
return redirect(list_)
return render(request, 'lists/list.html', {'list': list_, "form": form})
In my experience with Django, there are 2 things you often (always?) need to do to get static files to "refresh" after pushing them to a remote server:
Run ./manage.py collectstatic to make sure all your static files are in the right place.
While sshed into your server run the command sudo reboot now to restart your server (note that this will kick you out of your ssh session, and your server will be unreachable for a moment - usually just a few seconds in my case).
As for step 2 there might be a better way to do this, but in my experience, when I update static files the updated version is not served until I do this, and restarting nginx or the like is not sufficient for the changes to take effect. Note that this will mean that your site, if live, will not be reachable for a few seconds while the server is restarting (which is what makes me think there might be a better way to do it) but for me and my small user base this is not a big issue.
From reading some other posts about static files not updating, it seems like it could also be the case that your browser is caching the static files, and that restarting your browser/clearing the cache might do the trick as well, but I have not had a chance to try this yet.
I have a Django project set up with an app called pub. I'm trying to set it up so that I can include urls.py from each app (there will be more as I go) in the top-level urls.py. I've also got a template that uses the 'url' function to resolve a URL on a view, defined in the openidgae module. The problem is that after the httprequest is routed to pub.views.index (like it's supposed to), I try to respond by rendering a template that uses the template 'url' function. The code I'm showing below is also here: http://gist.github.com/243158
Here's my top-level urls.py:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'', include('openidgae.urls')),
(r'^pub', include('pub.urls')),
)
and pub/urls.py:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'', 'pub.views.index'),
(r'^/$', 'pub.views.index'),
)
and templates/base.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>{% block title %}My amazing site{% endblock %}</title>
</head>
<body>
<div id="header">
{% if lip %}
Welcome {{ lip.pretty_openid }}
logout
{% else %}
<form id="login-form" action="{% url openidgae.views.OpenIDStartSubmit %}?continue={{continueUrl}}" method="post">
<input type="text" name="openid_identifier" id="openid_identifier" />
<input type="submit" value="Verify" />
</form>
<!-- BEGIN ID SELECTOR -->
<script type="text/javascript" id="__openidselector" src="https://www.idselector.com/selector/46b0e6d0c8ba5c8617f6f5b970865604c9f87da5" charset="utf-8"></script>
<!-- END ID SELECTOR -->
{% endif %}
</div>
{% block content %}{% endblock %}
</body>
</html>
and templates/pub/index.html:
{% extends "base.html" %}
{% block title %}blahblah!{% endblock %}
{% block content %}
blahblahblah
{% endblock %}
and finally, pub/views.py:
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django import forms
import openidgae
def index(request):
lip = openidgae.get_current_person(request, HttpResponse())
resp = render_to_response('pub/index.html', {'lip': lip})
return resp
Now, if i set the second pattern in my top-level urls.py to point directly to 'pub.views.index', all works like it should, but not if I use the include function.
Any ideas? I'm sure the problem has something to do with the urlpattern that would map the views I'm trying to resolve to URLs not being available to the template rendering functions when the HttpRequest is handled by the pub app rather than by the top-level, but I don't understand why or how to fix it.
I don't understand what the problem is that you're facing, but just by looking at your urls.py files, you should probably change the top level urls.py to something like
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'', include('openidgae.urls')),
(r'^pub/', include('pub.urls')),
)
and pub/urls.py to:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^$', 'pub.views.index'),
)
if you then use {% url pub.views.index %} somewhere in your templates, you should get the correct url.
You post a lot of code, but you haven't been very clear about what the actual problem is. First of all having
(r'', 'pub.views.index'),
(r'^/$', 'pub.views.index'),
can give some problems if you want to find the url. What should the url be for pub.views.index? From what you say, this is actually not be a problem, since you don't have a template tag that want to reverse the mentioned view. You don't actually say what is going wrong. But a way to fix the above problem, if you want to keep the two urls, would be to used named urls. I find it a bit redundant since you can just redirect example.com/pub to example.com/pub/, but you could transform the above to:
url(r'', 'pub.views.index' name='pub_a'),
url(r'^/$', 'pub.views.index', name='pub_b'),
Doing this you are now able to reverse your url, as you can uniquely identify them doing {% url pub_a %} or {% url pub_b %}. This would also make your templates easier to read, as you can give names that mean something, so it's easier to remember what's going on, while being more concise.