Add StreamingHttpResponse into middle of Django template - python

Python 3.6.3, Django 2.0.3
I'm new to django, but I'm trying to make a pretty simple site where someone can trigger a few tasks that were previously just misc, stand-alone python scripts. Unfortunately those tasks can take a pretty long time. I want to be able to display the output from those tasks in the middle of the following template (where {{ stream }} is) so the user has some meaningful feedback.
{% load pagePieces %}
{% page_header %}
<div class="container">
<div class="row">
<a class="btn" href="/"><i class="fa fa-chevron-left"></i> Home</a>
</div>
<div class="row row-header"><h1>{{ operation }}</h1></div>
<div class="row row-content">
{{ stream }}
</div>
</div>
{% page_footer %}
In my view file I've tried a few different things, but here's about where I'm at now (this is somewhat simplified. I took out some error handling and changed some names):
def myaction(request):
output_template = loader.get_template('myapp/process_output.html')
return StreamingHttpResponse(
output_template.render({
'operation': 'That long running task',
"stream": streaming_wrapper()
})
)
def streaming_wrapper():
output_template = loader.get_template('myapp/process_output.html')
x = yield from a_module.long_running_task()
yield output_template.render({
'operation': 'That long running task',
"stream": x
})
This does stream the output from long_running_task(), but doesn't load the rest of the template until after it's done. At other points, I've gotten the output to stream after the template, but never in the middle, which looks bad because my template has a header and a footer.
I'm not sure how to make this work, and I'm not sure if the answer is in my views or perhaps doing something more complicated with my template.
(I'm also aware this is similar to these 2 questions, but neither of them have satisfactory answers and are years old.
Django: return a StreamingHttpResponse on an existing html page
Django StreamingHttpResponse into a Template)

Try to implement the steps as per this blog of Miguel Grinberg - https://blog.miguelgrinberg.com/post/video-streaming-with-flask/page/8 (This is for for Flask). But you have to follow the same steps and also need to modify the template as per the need. These steps worked for me.

Related

Django Template Not Displaying Variables Correclty

I have a django page which is making an API call then displaying the results through a template. This has been working well but I must have changed something and now half the variables are not displaying correctly. Usually when there is an error calling a variable the template would just display a blank field. However, in my situation the webpage is displaying the code which is calling the variable. Here is what I have:
My HTML Code Looks like this:
<h6>Page</h6>
<ul class="list-inline mx-auto row">
<li class="list-group-item col-md-12">ASN: {{ context.upload.urlscan.page.asn }}</li>
</ul>
<ul class="list-inline mx-auto row">
<li class="list-group-item col-md-12">ASN Name: {{ context.upload.urlscan.page.asnname }}</li>
</ul>
<ul class="list-inline mx-auto row">
<li class="list-group-item col-md-12">IP: {{ context.upload.urlscan.page.ip }}</li>
</ul>
From this code ONLY the first and third line are displaying correctly - These lines are displaying the variables that they are assigned to.
The middle value Labeled 'ASN Name' is displaying the code back. On the webpage it looks like this:
{{ context.upload.urlscan.page.asnname }}
I have verified that the data is coming in correctly and this is happening in several places in my code. Not sure why some variables are working and some are not.
I am using Django 2.1 and Python 3.6 on RHEL 7.x
EDIT
Per the request here is my context creation and render portion
context['type'] = 'url'
context['upload']['cs_response'] = cs_response
context['upload']['cs_domain'] = cs_resp_dom
context['upload']['ppdom_rep'] = ppdom_rep
context['upload']['ppdom_ids'] = ppdom_ids
context['upload']['cs_test'] = ioc
context['upload']['urlscan'] = scan_res
context['js'] = json.dumps(context, indent=4)
return render(request, 'iocs/upload.html', {'context': context})
So this was a pain but I finally figured it out. I wanted to style a div and I did it in a kinda lazy way. My django template was extended from a 'base' template so right under the {% block content %} tag I added a <style> tag.
This worked and styled the div correctly, however for some reason it broke half my variables on the page. I HAVE NO IDEA WHY! When debugging I commented this entire <style> block out and my code was still broken. I had to completely delete the <style> block for it to work again.
Once the <style> block was removed all variables began working...

Nested Django view with .html inserted using include tag

I would like to know if anyone has any best practice recommendations for rendering a view within a view in Django, or something with a similar effect where both views can have their own context and methods.
I am currently rendering the dropdown using the built-in include tag. So the nested .html is using the same Django view as the rest of the page. And all the context is coming from the main view as shown below. I would like to give this dropdown its own Django view so that I only perform certain database queries and other calculations if the dropdown is opened.
<div class="container-fluid">
<div class="row">
<div class="col-6">
</div>
<div class="col-2 d-flex justify-content-center">
{% include nested.html %}
</div> ...
It would be nice if someone with experience in this could let me know what they think, and if it even makes sense to try and split this into 2 views.
In summary. I would like to know if I can somehow render a separate view using something similar to the include Django tag. So that I have control over where the view gets rendered.
Below I have outlined my implementation of the solution below, using custom inclusion tags as suggested in the comments to my question.
You can make a custom template tag file in project directory and then register these in the template library. e.g:
template_tags.py
from django import template
from users.models import Organisation
register = template.Library()
#register.inclusion_tag('nested.html', takes_context=True)
def nested_template(context, param=None): #param to pass variables from main view
context.update({
'data_list': get_data_list(param)
'organisation_id': param,
})
return context
def get_data_list(self,param):
data_list = ... #do all queries needed.
return data_list
In the template tag you point to your nested.html which does whatever you need it to do. For example:
nested.html
{% for data in data_list %}
<h4> {{data}} </h4>
{% endfor %}
Then to include the template, in your main view template:
{% load nested_template %} #at the top or anywhere before using it
{% nested_template param %} #where you want the template included
Hopefully clear enough and may assist someone

Sending messages using Django Postman

I am trying to use Django-Postman and have gotten as far as being able to see the templates on the webpage after I press the link but I don't know how send messages works. According to the write view there should be a form loaded but all I get is the links to the other pages in the template. If someone could explain how to get this to work it would be fantastic.
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav ">
<li>MyCourse</li>
<li>Timetable</li>
<li>logout</li>
<li>Inbox</li>
</ul>
</div>
Recently had to set up postman myself, and based just off your snippet, I'm going to assume you wrote the ul element yourself.
So, if that's the case, postman actually expects to handle all of that for you. According to the docs, you need to create a base.html template inside your own template directory. A few blocks are expected to be present inside this template, namely {% title %} (text it will add to the page's title), {% extrahead %} (some extra js and css), {% content %} (would contain the missing forms you're looking for) and {% postman_menu %} (the menu links automatically generated by postman).
You could always create the menu links yourself, but I'd suggest you create a /postman folder in your app's template folder, then copy the base.html from the installed postman app (this contains the code for how to layout the ul). Just a little more django-esque, and usefull if you need to fiddle with the names of the template tags, etc, but that's up to you.
Hope this helps, happy coding.

How to use django base extension along with angularjs ng-include?

I'm using ng-include like this
HTML
<div ng-app="myapp" ng-controller="myctrl" ng-include="/static/html/main.html"></div>
main.html
{% extends "app\base.html" %}
{% block content %}
<div ng-controller="myctrl1">
some content
</div>
{% endblock %}
base.html
<div ng-controller="myapp2">some content </div>
but this is not working, it is showing an errorr "SyntaxError: Unexpected token % at Object.parse (native)"
Please suggest me a better way to implement this.
I don't quite know what you're trying to do here. Angular templates and Django ones are quite different, even if they superficially share the same {{ var }} syntax. You can't inherit an Angular template from a Django one, or vice versa.
But there's no reason to want to do that anyway. Angular is already loading the template as a partial, which means it will be inserted into the div in base.html. There's no need for inheritance here at all.

django template conditional html

I'm not sure if the title is technically correct (sorry, I'm new to python+django)
I have a template page that displays whether an application is running or stopped depends on its status. For example:
If app is running I want to display:
<div class="lt">
<a class="play" title="App running">
<span class="text_play">Running</span>
</a>
</div>
<div class="rt">
<input type="submit" onclick="stop_app()" value="stop" class="stop">
</div>
If the application is not running then show this instead:
<div class="lt">
<input type="submit" onclick="star_app()" value="start" class="play">
</div>
<div class="rt">
<a class="stop" title="Application is not running">
<span class="test_stop">Not Running</span>
</a>
</div>
This is kind of stripped down simplified html but my point is how can I avoid repeating myself?
The template is passed a dictionary of applications that it iterates over to display all the applications and their status (running/stopped). So currently I'm iterating over the dict twice, one for "stopped" apps and one for the "running" apps.
Hope it's clear
Thanks in advance
EDIT: This is what I have tried so far:
{% if application.service.status|lower == "enabled" %}
<div>...display running HTML...</div>
{% else %}
<div>...display the non-runing HTML..</div>
{% endif %}
I just want to know if I'm doing the right thing (DRY?)
What you proposed is pretty DRY.
{% if application.service.status|lower == "enabled" %}
<div>...display running HTML...</div>
{% else %}
<div>...display the non-runing HTML..</div>
{% endif %
Keep in mind you'll rely on the return render(request... for determining the html Django needs construct.
Your proposed solution will choose one or the other. I.e. if your non-running HTML needs to switch to running HTML you won't have access to it without another render.
To be more clear and concise, django templates will construct the appropriate HTML leaving out the alternative options or "conditions".
If you learn a bit of jQuery for example you can have elements of the page switch the currently displayed html. Expanding this to ajax will allow you to get status updates from the server and vice versa.

Categories

Resources