I can't seem to figure out how to add my graph to a Class Detail View? Is it not possible to do so? I add it to the detailView, and call it in my template with:
{{ div | safe }}
But it does not show? I've gotten it to work perfectly fine in a view and template separately.
Here's the whole detailview I'm trying to implement it into.
DetailView
class MedarbejderDetailView(FormMixin, DetailView):
template_name = 'evalsys/medarbejder/detail.html'
model = Medarbejder
form_class = OpretEvalForm
def evalgraph(self):
colors = ["#40e862", "#ff9d26", "#ff1424"]
over = 0
møder = 0
under = 0
none = 0
counts = []
items = ["Overstiger forventning", "Møder forventning", "Under forventning", "Ingen bedømmelse"]
eval_vudering = Evaluering.objects.values("vuderingsnavn__vuderingsnavn")
source = ColumnDataSource(data=dict(items=items, counts=counts))
for i in eval_vudering:
if "Overstiger forventning" in i.values():
over += 1
elif "Møder forventning" in i.values():
møder += 1
elif "Under forventning" in i.values():
under += 1
elif None in i.values():
none += 1
counts.extend([over, møder, under, none])
plot = figure(x_range=items, plot_height=500, plot_width=500, title="Opsumering af evalueringer",
toolbar_location=None, tools="pan, wheel_zoom, box_zoom, reset, tap", tooltips="@items: @counts")
plot.title.text_font_size = "20pt"
plot.vbar(x="items", top="counts", width=0.9, source=source, legend="items", line_color='black',
fill_color=factor_cmap("items", palette=colors, factors=items))
plot.legend.label_text_font_size = "13pt"
script, div = components(plot)
return render(self, 'evalsys/medarbejder/detail.html', {'script': script, 'div': div})
def view_medarbejder_with_pk(self, pk=None):
if pk:
medarbejder = Medarbejder.objects.get(pk=pk)
else:
medarbejder = self.medarbejder
args = {'medarbejder': medarbejder}
return render(self, 'evalsys/medarbejder/detail.html', args)
def get_context_data(self, **kwargs):
context = super(MedarbejderDetailView, self).get_context_data(**kwargs)
context['eval_list'] = Evaluering.objects.all()
context['fag_list'] = Fag.objects.all()
context['ma'] = Medarbejder.objects.get(pk=self.kwargs.get('pk'))
context['instruktør'] = User.objects.get(username=self.request.user)
return context
def post(self, request, pk):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
print(form.cleaned_data)
instance = form.save(commit=False)
instance.instruktør = request.user
instance.ma = self.object
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
item = form.save()
self.pk = item.pk
return super(MedarbejderDetailView, self).form_valid(form)
def form_invalid(self, form):
return super(MedarbejderDetailView, self).form_invalid(form)
def get_success_url(self):
return reverse_lazy("evalsys:view_evaluering_with_pk", kwargs={'pk': self.pk})
URLs
path('se_alle_evalueringer/<int:pk>', views.MedarbejderEvalDetailView.as_view(), name="view_evaluering_with_fag"),
I know I'm calling the function "view_evaluering_with_fag", so it is because I'm not calling my Bokeh function "evalgraph"?
Didn't know folks couldn't use this as a way to ask follow up questions when we're researching the same question.
Anyhow, I am so about to make your day! With A LOT of trial and error (I've only been coding with Python and Django for a month with no real coding background except Java back in 1999) I got bokeh to render from detailview. It appears the trick is to get stuff under the get_context_data function. I don't know how I came to this conclusion, but I figured the script and div context weren't making their way to the render so I was trying to get them into context. As you'll see below, I put script and div as context['script']=script and context['div']=div. My situation looks a bit simpler, I'm just parsing a bike data file and plotting the data, but hopefully this gets you on your way if you're still trying to make this work.
class FitFileDetailView(DetailView):
model = FitFiles
def get_context_data(self, **kwargs):
model = FitFiles
ff = FitFiles.objects.get(pk=self.kwargs.get('pk'))
ffile = ff.fitfiles.path
fitfile2 = FitFile(ffile)
while True:
try:
fitfile2.messages
break
except KeyError:
continue
workout2 = []
for record in fitfile2.get_messages('record'):
r2 = {}
# Go through all the data entries in this record
for record_data in record:
r2[record_data.name] = record_data.value
workout2.append(r2)
df2 = pd.DataFrame(workout2)
df2['time']=(df2['timestamp'] - df2['timestamp'].iloc[0]).astype('timedelta64[s]')
#Bokeh code
df2 = pd.DataFrame(workout2)
df2['time']=(df2['timestamp'] - df2['timestamp'].iloc[0]).astype('timedelta64[s]')
p2 = figure(x_axis_label='time', y_axis_label='watts', tools="", plot_width=1000, plot_height=500)
p2.line(df2['time'], df2['power'])
p2.line(df2['time'], df2['heart_rate'], color='red')
script, div = components(p2)
context = super(FitFileDetailView, self).get_context_data(**kwargs)
context['script']=script
context['div']=div
return context