Combining Python code inside HTML with variables passed in - python

I am creating a web store with HTML and Bottle (Python). I know how to pass data between HTML and Python, as well as how to write Python code inside HTML (reference: http://karrigell.sourceforge.net/en/pythoninsidehtml.html).
What I struggle with is writing Python code inside the reference that gets passed from HTML to Python.
I load images from a database since I have a lot of them. I set and pass the variables image_name(index) to HTML like this:
#get('/store')
def showStore():
images = models.images() # reads from database
data = ', number_of_images={}'.format(len(images))
for (id, title, path) in images:
data += ', image_name{}={}, '.format(id, path)
data += 'image_title{}={}'.format(id, title)
return template('store.html' + data)
The relevant part of store.html:
<!-- Portfolio Gallery Grid -->
<div class="row">
<% for i in range(1, number_of_images+1): %>
<div class="column">
<div class="content">
<img src="static/images/{{image_name<%i%>}}.jpg">
<h3> {{image_title<%i%>}} </h3>
</div>
</div>
<% end %>
</div>
Since Bottle is not that well known: {{image_title}} in HTML gets the value passed in from the template (html, variables). Block <% %> enables you to write Python code inside it.
Everything worked properly when I didn't use indexing of image properties inside the HTML, so HTML and the for loop do work, the problem is with this part:
{{image_title<%i%>}}
<%i%> should in my opinion create a variable image_titlei but apparently it doesn't.
I get a template not found error, probably because the variables I am passing in (from the .py file) do not exist in the HTML.
The reason I would very much like to do this dynamically instead of hardcoding every image is that I have a lot of those images and every image has a whole table of relevant data I left out here because I would retrieve it in the same way as image's name and title.
I would appreciate any help with proper combining Python inside HTML with variables passed in since I really want to do it dynamically

There are a rather large number of things wrong here.
Your template not found error is actually nothing to do with the strange manipulations you are doing within that template. It is because you are concatenating the template name with the data string in your call to template() in the last line of your Python code. I don't know bottle, but I'm absolutely positive the data needs to be a second parameter to that function:
return template('store.html', data)
As for the rest, there's absolutely no need to do anything that you are doing there. Just pass the images as a list, and iterate through that list in the templates. Dynamic variables are always a bad idea, and that applies just as much to templates as it does to standard Python code.
(Although note that you don't even create any dynamic variables; you just have a single string, formatted to look like a set of variable assignments. But that doesn't make it actually assign any variables anywhere.)

Related

How to get variables between the curly brackets in django template in django views?

I have django template file. Now i want to get all the variables list that are between curly brackets. I think it is possible with the regular expressions. And i read about regular expressions. But there is no function i found to be helpful.
template code snippet:
<tr><td>
Dear Candidate,<br/>
Welcome to Creative Talent Management!<br/>
We have created an account for you. Here are your details:<br/>
Name:{{name}}<br/>
Email:{{email}}<br/>
Organization:{{organization}}<br/>
Password:{{password}}<br/>
</td></tr>
I want to get name,email,organization,password in my python function.
Right now i'm reading the template but getting empty list.
if created:
temp_path = str(instance.html_template.path)
html_file = open(instance.html_template.path, 'r', encoding='utf-8')
file_data = html_file.read()
render_param = re.findall("^{{ . }}$", file_data)
print("html param ",render_param)
That's sort of back-to-front. You would normally pass all the variables which might be used from your view to the template rendering through the context. It doesn't matter if one or more of the context variables are unused by the template. Of course, you should have a test which catches variable name spelling errors ({{usernmae}} will render as null string without error ).
For checking the template, you might simply grep '{{' some_template.html, or write something in Python to get (say) an alphabetically sorted list of variable names. But that's a program-development aid, not a part of the Django server code.
If you really wanted to, you could just open the template file and write similar Python code as part of your view. But, why??

Sending and rendering HTML syntax via jinja variable

I need some complicated operations to render some dynamic trees in my front-end. But as I can't find any way to run recursion in my jinja or front-end, I take an approach to make a string in my views.py along with HTML syntax and render them in the front-end to get the desired output something like this (As an example, here I skip the original complicated string because there is no need for it):
in views.py:
test = "<h2>Hi This is from django</h2><ol><li>abc</li><li>mno</li><li>xyz</li></ol>"
mydict={
'test' : test,
}
return render(request, 'app\index.html', mydict)
In index.html:
<div class="container-fluid">
{{ test }}
</div>
My desired output with this code is:
Hi This is from
djangoabcmnoxyz
But the obtain output is:
<h2>Hi This is from django</h2><ol><li>abc</li><li>mno</li><li>xyz</li></ol>
Please suggest to me, is there any way to render the jinja string variable along with the effect of HTML in my front-end? If not then how can I take an approach to render any tree dynamically in my front-end where the level, leaf node, intermediate node, etc all info come from the database.
You can use the django-template-filter safe for this.
{{ test | safe }}

Django - How to make anchors change HTML list

I have the following snippet of HTML:
On my django webpage, i get a list that looks as follows:
Each "Part" anchor corresponds with a Part object in Python. Now, I'd like to make it so that when the user clicks on "Part_2", the datapoints of that Part are shown just below it.
On the image, the datapoints of the first part are shown within the nested list. I hard coded this. I looked into calling a python function with an argument from the template, but that is not possible.
What would be an easy way to make this happen?
You can achieve this on the client side. First, create a detail element in your HTML and put a summary and the tags that you need (in this case, I'll be using a <p></p>) as childs:
<details>
<summary>Part 1</summary>
<p>Epcot is a theme park at Walt Disney World Resort featuring exciting attractions, international pavilions, award-winning fireworks and seasonal special events.</p>
</details>
What's inside the summary tag will represents the title and below that goes the hidden text that can be accessed by clicking in the arrow on the side of the title.
Then, make sure you filter in your function in views.py the parts by part_1 and part_2 and then pass them into your context. Lastly, render the items like this:
<details>
<summary>Part 1</summary>
{% for part in part_1 %}
<p> {{ part.tag }}</p>
{% endfor %}
</details>

Only extract information from the div class if it contains a certain word using xpath

I am trying to scrape information from the following website https://www.rawson.co.za
However, sometimes, the information changes it's position.
I am struggling to check for only the 'Building size' and store that as the size, since the div class looks like this:
<div class="features__item">
<div class="features__icon icon-house" aria-hidden="true"></div>
<div class="features__label">Building Size 130m²</div>
</div>
I am able to extract that but sometimes it takes other information due to the property either not having it or something else being at the position of it.
This is what i have for size now (I am accessing the information from the child/property pages):
size = response.xpath("//div[#class='features']/div[#class='features__list']/div[#class='row']/div[#class='col col--1-2'][2]/div[#class='features__item'][1]/div[#class='features__label']/text()").re(r'\d+')[0]
What I would like to take is the Building size information(only numbers) if it exists and put None if there is no building size available. I am struggling with the text part in the div class. I have tried to construct a for loop that will check if it contains the ''Building Size'' but nothing has worked yet. Any help would be very much appreciated! Thank you!
Simple:
size = response.xpath("//div[#class='features__label'][contains(., 'Building Size')]/text()").re_first(r'\d+')

Error accessing the class having hyphen(-) separated names in html file using BeautifulSoup

I am trying to scrape the data of popular english movies on Hotstar
I downloaded the html source code and I am doing this:
from bs4 import BeautifulSoup as soup
page_soup = soup(open('hotstar.html'),'html.parser')
containers = page_soup.findAll("div",{"class":"col-xs-6 col-sm-4 col-md-3 col-lg-3 ng-scope"})
container = containers[0]
# To get video link
container.div.hs-cards-directive.article.a
I am getting an error at this point:
NameError: name 'cards' is not defined
These are the first few lines of the html file:
<div bindonce="" class="col-xs-6 col-sm-4 col-md-3 col-lg-3 ng-scope" ng-repeat="slides in gridcardData">
<hs-cards-directive cdata="slides" class="ng-isolate-scope" renderingdone="shownCard()">
<article class="card show-card" ng-class="{'live-sport-card':isLiveSportCard, 'card-active':btnRemoveShow,'tounament-tray-card':record.isTournament}" ng-click="cardeventhandler({cardrecord:record})" ng-init="init()" pdata="record" removecard="removecard" watched="watched">
<a href="http://www.hotstar.com/movies/step-up-revolution/1770016594" ng-href="/movies/step-up-revolution/1770016594" restrict-anchor="">
Please help me out!
I am using Python 3.6.3 on Windows.
As (loosely) explained in the Going down section of the docs, the tag.descendant syntax is just a convenient shortcut for tag.find('descendant').
That shortcut can't be used in cases where you have tags whose names aren't valid Python identifiers.1 (Also in cases where you have tags whose names collide with methods of BS4 itself, like a <find> tag.)
Python identifiers can only have letters, digits, and underscores, not hyphens. So, when you write this:
container.div.hs-cards-directive.article.a
… python parses it like this mathematical expression:
container.div.hs - cards - directive.article.a
BeautifulSoup's div node has no descendant named hs, but that's fine; it just returns None. But then you try to subtract cards from that None, and you get a NameError.
Anyway, the only solution in this case is to not use the shortcut and call find explicitly:
container.div.find('hs-cards-directive').article.a
Or, if it makes sense for your use case, you can just skip down to article, because the shortcut finds any descendants, not just direct children:
container.div.article.a
But I don't think that's appropriate in your case; you want articles only under specific child nodes, not all possible articles, right?
1. Technically, it is actually possible to use the shortcut, it's just not a shortcut anymore. If you understand what getattr(container.div, 'hs-cards-directive').article.a means, then you can write that and it will work… but obviously find is going to be more readable and easier to understand.

Categories