Django context isn't passing information to template - python

I try to pass information to an html template from a view function. Every time I try to call the variable from the html template it doesn't show anything.
Here is my configure_peplink.html:
{% extends "base_generic.html" %}
{% block content %}
<h1>Configure Peplink</h1>
<p>Configure a Peplink router from the web. This was designed by <em>Valorence LLC</em></p>
{% if peplink %}
<p>Serial Number: {{ peplink.serial_number }}</p>
<p>IP Address: {{ peplink.ip_address }}</p>
<p>Mac Address: {{ peplink.mac_address }}</p>
<p>Name: {{ peplink.name }}</p>
{% else %}
<p>No Data Found Off Device</p>
{% endif %}
{% endblock %}
Here is the view function configure_peplink:
def configure_peplink(request, peplink):
selected_peplink = PeplinkDevice.objects.get(serial_number=peplink)
print(selected_peplink.ip_address)
print(selected_peplink.serial_number)
print(selected_peplink.mac_address)
context = {
'peplink': selected_peplink
}
return render(request, 'configure_peplink.html', context=context)
Here is the url line to call the view:
re_path(r'^configurepeplink/(?P<peplink>.*)/$', views.configure_peplink, name='configurepeplink')
I've tested to make sure that the context has data in it (as seen with the print statements). Even though the context variable has data and is getting past the if statement in the html template it still doesn't display any data. I have tried clearing my cache on the browser and restarting all my services (django, celery, redis-server).
Here is a picture of the webpage:

The peplink variable (which is being used by the regex url and the view function) seems to be causing the problem. Change the name of the key or change the regex url variable for this to work. To get this to work by changing the key name in the view function do the following in the view function:
def configure_peplink(request, peplink):
selected_peplink = PeplinkDevice.objects.get(serial_number=peplink)
print(selected_peplink.ip_address)
print(selected_peplink.serial_number)
print(selected_peplink.mac_address)
context = {
'selected_peplink': selected_peplink
}
return render(request, 'configure_peplink.html', context=context)
Then change the html template to the following:
{% extends "base_generic.html" %}
{% block content %}
<h1>Configure Peplink</h1>
<p>Configure a Peplink router from the web. This was designed by <em>Valorence LLC</em></p>
{% if selected_peplink %}
<p>Serial Number: {{ selected_peplink.serial_number }}</p>
<p>IP Address: {{ selected_peplink.ip_address }}</p>
<p>Mac Address: {{ selected_peplink.mac_address }}</p>
<p>Name: {{ selected_peplink.name }}</p>
{% else %}
<p>No Data Found Off Device</p>
{% endif %}
{% endblock %}

Related

Content not visible on webpage

I am creating a database website with python and django. My problem is that the content I try to get data from my class' fields doesn't appear on the id-page on django. I am able to make a successful search, and I get links for my searches. The name-field is visible in searches and on the page, but nothing else appears. When I click on the link, I go to luokka_id/number. I must be missing something but can't figure out what the problem is.
models.py
class luokka(models.Model):
nimi = models.CharField('Pääkäyttöluokka', max_length=100)
vara = models.CharField('Varakäyttöluokka', max_length=100)
varaaja = models.CharField('Varakäyttöluokka', max_length=100)
def __str__(self):
return self.nimi
and on the näytä_luokka.html (show class):
{% extends 'tietokanta/base.html' %}
{% block content %}
<center>
{{luokkalistaus}}
{{luokka}}
{{ luokka.nimi }}
{{ luokka.vara }}
{{ luokka.varaaja }}
</center>
{% endblock %}
and views.py:
def näytä_luokka(request, luokka_id):
luokkalistaus = luokka.objects.get(pk=luokka_id)
return render(request, 'tietokanta/näytä_luokat.html',
{'luokkalistaus': luokkalistaus})
I don't get any errors to help me out here. It's just an empty page, but it should show some extra data.
You have named the key of context as luokkalistaus not luokka, so the template should be:
{% extends 'tietokanta/base.html' %}
{% block content %}
<center>
{{ luokkalistaus.nimi }}
{{ luokkalistaus.vara }}
{{ luokkalistaus.varaaja }}
</center>
{% endblock %}

I have to call multiple webpages to extract information for a django application and then display it but I don't know how to display properly

My issue is that when I have called an external webpage and displayed as {{ html }} in the for loop it prints for all of them is there a way to print just for one. The part after b'{"carpark_name": "multi-storey", "date": "01-11-21 12:46:55", "spaces_available": 332}'
this is the webpage
This is my views.py
from django.shortcuts import render
from .models import Carpark, Campus
from urllib.request import urlopen
def index(request):
campus_list = Campus.objects.all()
carpark_list = Carpark.objects.all()
noparking = Campus.objects.filter(carpark=None)
html = urlopen("https://mbezbradica.pythonanywhere.com/carparks/multi-storey").read()
context = {'carpark_list': carpark_list,
'campus_list': campus_list,
'noparking': noparking,
'html' : html
}
return render(request, "parkatdcu/index.html", context)
And this is my index.html code
<h1>Welcome to ParkAtDCU</h1>
{% for campus in campus_list %}
<h2>
{{ campus }}
</h2>
{% if campus in noparking %}
No carparks found
{% else %}
<ul>
{% for carpark in carpark_list %}
{% if campus == carpark.campus_id %}
<li> {{ carpark.name }}: {{ carpark.spaces}} spaces, {{carpark.disabled_spaces}} spaces for people with disabilities, {{ html }}</li>
{% endif %}
{% endfor %}
{{ url }}
</ul>
{% endif %}
{% endfor %}
What you are getting is a bytes object, you can decode it into a string object and use ast.literal_eval() to convert it into a dictionary. And then pass that dictionary into the template. Honestly this is a JSON object and you should not call it HTML. I'll give it the name data here. And then in the template just call whatever you can want to show:
from django.shortcuts import render
from .models import Carpark, Campus
from urllib.request import urlopen
import ast
def index(request):
campus_list = Campus.objects.all()
carpark_list = Carpark.objects.all()
noparking = Campus.objects.filter(carpark=None)
html = urlopen("https://mbezbradica.pythonanywhere.com/carparks/multi-storey").read()
data_string = html.decode("utf-8")
data = ast.literal_eval(test_string)
context = {'carpark_list': carpark_list,
'campus_list': campus_list,
'noparking': noparking,
'html' : data
}
return render(request, "parkatdcu/index.html", context)
And in your html file:
<h1>Welcome to ParkAtDCU</h1>
{% for campus in campus_list %}
<h2>
{{ campus }}
</h2>
{% if campus in noparking %}
No carparks found
{% else %}
<ul>
{% for carpark in carpark_list %}
{% if campus == carpark.campus_id %}
<li> {{ carpark.name }}: {{ carpark.spaces}} spaces, {{carpark.disabled_spaces}} spaces for people with disabilities, car park name: {{ html.carpark_name }}</li>
{% endif %}
{% endfor %}
{{ url }}
</ul>
{% endif %}
{% endfor %}
But the way you are doing it is very dirty (in my opinion). I suggest you install requests and use requests.get(url).json() it will give you a dictionary without going through this hassle, making you code cleaner (again, in my opinion).
You can install requests:
pip install requests
and do this:
from django.shortcuts import render
from .models import Carpark, Campus
from urllib.request import urlopen
import requests
def index(request):
campus_list = Campus.objects.all()
carpark_list = Carpark.objects.all()
noparking = Campus.objects.filter(carpark=None)
data = requests.get("https://mbezbradica.pythonanywhere.com/carparks/multi-storey").json()
context = {'carpark_list': carpark_list,
'campus_list': campus_list,
'noparking': noparking,
'html' : data
}
return render(request, "parkatdcu/index.html", context)
(I didn't change your html context variable because "if it works, don't touch it", I suggest you change your context variable name "html" to "data" or something like that).

Django How can I cache properly to reuse data?(with using django-mptt package and redis module)

I am making kind of dynamic menu. when you click menu on the top, it show sub menu on the left side. I searched with keyword 'dynamic menu' from stackoverflow and google. I got idea to build that kind of menu. I made it like below.
1) render data(menu list) in context to template by custom context processor.
2) using custom template tag which is provided by django-mptt package.
3) show top menu in base template.
4) move to another template to show sub menu according to what top menu you click
I made custom context_processor to use menu in context in every template.
context_processor.py
from manager.models import Menu
def menu(request):
menu_list = list(Menu.objects.all())
return {'menu':menu_list}
template.py(example)
{% load mptt_tags %}
<nav id="{{ menu_id }}" class="tree-menu">
<ul>
{% recursetree menu %}
<li class="menu
{% if node.is_root_node %}root{% endif %}
{% if node.is_child_node %}child{% endif %}
{% if node.is_leaf_node %}leaf{% endif %}
{% if current_menu in node.get_descendants %}open{% else %}closed{% endif %}
">
{{ node.menu_name }}
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }}
</ul>
{% endif %}
{% if node.items and node.items.exists %}
<ul class="items">
{% for item in node.items.all %}
{% if item_template %}
{% include item_template %}
{% else %}
{% include "menu/tree-item.html" %}
{% endif %}
{% endfor %}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
</nav>
mptt_tags.py
#register.tag
def recursetree(parser, token):
"""
Iterates over the nodes in the tree, and renders the contained block for each node.
This tag will recursively render children into the template variable {{ children }}.
Only one database query is required (children are cached for the whole tree)
Usage:
<ul>
{% recursetree nodes %}
<li>
{{ node.name }}
{% if not node.is_leaf_node %}
<ul>
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
"""
bits = token.contents.split()
if len(bits) != 2:
raise template.TemplateSyntaxError(_('%s tag requires a queryset') % bits[0])
queryset_var = template.Variable(bits[1])
template_nodes = parser.parse(('endrecursetree',))
parser.delete_first_token()
return RecurseTreeNode(template_nodes, queryset_var)
My Question
If you see django manual about QuerySet, it says that "Each QuerySet contains a cache to minimize database access". It is obvious that, if you query same data in certain rule, it doesn't seem hit database again but return result from cache. Then I am querying Menu.objects.all() in custom context processor. This result(menu_list = Menu.objects.all()) will be in context every time, you can use menu data on every template repeately. So does it reuse the result from cache without hitting database again?
If menu_list = Menu.objects.all() in custom context processor hit database every time whenever template load this menu list, Does it work in this way to reuse menu data from cache without hitting database everytime?
context_processors.py
from manager.models import Menu
from django.core.cache import cache
def menu(request):
menu_list = cache.get_or_set('menu_list', list(Menu.objects.all()))
return {'menu':menu_list, 'redis':"Food"}
Lastly, I don't know if there are many people using django-mptt package. I guess just a few people have experience using it in person. It says "Only one database query is required (children are cached for the whole tree)" so does it mean if I use django-mptt package and get menu from it on template, it automatically cache its data?
Well, I am not clear about django cache system.
It would be really appreciate if you can give me answer and insight for my questions. Thanks for reading!

Flask pagination example wont work missing "iter_pages"

I am working on a small web app to view some logfiles. But the
queries I issue to the database use to get very big.
I wanted to implement some pagination following this example pagination.
I put the class into a single file which gets loaded in the Flask view. Next I implemented
my pagination view like this:
#app.route('/index/', defaults={'page':1})
#app.route('/index/page/<int:page>')
def index(page):
count = db_session.execute("select host,facility,level,msg from messages").rowcount
tblqry = db_session.execute("select host,facility,level,msg from messages").fetchmany(size=1000)
if not tblqry and page != 1:
abort(404)
pagination = Pagination(page, PER_PAGE, count)
return render_template('index.html', pagination=pagination, tblqry=tblqry)
after that I created a macro file named _pagination_helper.html with the macro contents from the macro example. Then I imported the pagination_helper macro with:
{% from "_pagination_helper.html" import render_pagination %}
but when I then try to do something like this:
{{ render_pagination(host[0]) }}
flask claims:
UndefinedError: 'str object' has no attribute 'iter_pages'
so why does flask fails to find the 'iter_pages' because I included the pagination class in the views file?
And also I am not really sure where to put the URL Generation Helper from the How To.
Edit:
This is what my pagination_helper looks like:
{% macro render_pagination(pagination) %}
<div class=pagination>
{% for page in pagination.iter_pages() %}
{% if page %}
{% if page != pagination.page %}
{{ page }}
{% else %}
<strong>{{ page }}</strong>
{% endif %}
{% else %}
<span class=ellipsis>…</span>
{% endif %}
{%- endfor %}
{% if pagination.has_next %}
Next »
{% endif %}
</div>
{% endmacro %}
You are expected to pass a Pagination object to the macro, not a string. host[0] is a string, not the pagination value you created in your view function.
Use:
{{ render_pagination(pagination) }}

create templates on the fly / dynamically

I am currently writing a django app around a rather complex data model.
For many use cases, I need to build similar, but slightly differing templates (incl. graphviz etc..).
Now I wonder if there is a way to follow DRY and create the templates "on the fly", e.g. based on a nested tuple (of which one gets defined per use-case -> template).
Practically speaking I'd like to stop writing these:
static_template_case1.html
{% if program %}
{{ program.name }}
{% for process in program.process_set.all %}
{{ process.name }}
{% for step in process.step_set.all %}
{{ step.name }}
{% endfor %}
{% for control in process.control_set.all %}
{{ control.name }}
{% endfor %}
{% endfor %}
{% endif %}
and replace it with something in the following direction:
template_generator.py
structure_case1 = ("program"("process"("step","control")))
def onTheFlyTemplate(structure):
# iterate through structure
# build template dynamically
# return template
onTheFlyTemplate(structure_case1)
I was not able to find something similar and also don't know yet where to start generating templates on the fly, nor how to integrate it.
Within the views feels like a good starting point, (instead of loader.get_template('static_template_case1.html')).
Thanks for any hint sending me into the right direction as well as your thoughts if DRY is being "overdone" here.
Ralph
Edit
I got a step closer, doing the following:
In the view:
from django.template import Template
def templateGen():
return Template("Program: {{program.count}}")
#login_required
def test(request):
program = Program.objects.all()
t = templateGen()
c = RequestContext(request,locals())
return HttpResponse(t.render(c))
So far this is only a proof of concept. The real work will be to write a smart "templateGen()" listening to the nested tuple.
How about an inclusion tag?
#register.inclusion_tag('<your-template.html>')
def get_program(program_id):
return {'program': <some logic to return your Program object>}
Your main template:
{%load my-template-tags%}
<div id="my-div">
{%get_program program_id %}
</div>
And your template file:
{{ program.name }}
{% for process in program.process_set.all %}
{{ process.name }}
{% for step in process.step_set.all %}
{{ step.name }}
{% endfor %}
{% for control in process.control_set.all %}
{{ control.name }}
{% endfor %}
{% endfor %}
You'd have to pass in your program_id to the main template.

Categories

Resources