I can do this:
>>>some_string = 'this is {0} a {1}'
>>>print(some_string.format('totally', 'string'))
>>>this is totally a string
What I want to do is kind of form a html list like that. Is there any way I can do something like...
my_list_items = ['<li>One</li>', '<li>Two</li>', '<li>Three</li>']
my_list = """<ol>
{list}
</ol>"""
print(my_list).format(list=my_list_items)
and get
<ol>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ol>
The rationale being; I'm writing a small cgi app for my school. I would rather be able to keep template html pages and insert the right values when the cgi script calls the page in the manner below, than have a billion print calls in the cgi file itself, as that's scrappy and difficult to debug.
group = '11bg/En1'
AP = 'AP1'
def process_input(group, AP):
"""
Any processing necessary, followed by calling the template and inserting the values
"""
return read_file('pages/group_page.html').format(group=group, AP=AP)
print(process_input(group, AP))
I instantly realised I was being an idiot. Just turn the list into a string of course.
Related
I am struggling to understand how to create a link in django's templates.
in my views.py file I have a list of lists (so a table). One of the fields may or may not contain links.
Views.py
#tableToView is a pd.DataFrame()
actualTable = []
for i in range(tableToView.shape[0]):
temp = tableToView.iloc[i]
actualTable.append(dict(temp))
#Returning the 'actualTable' list of lists to be printed in table format in the template
return render(response, "manual/manualinputs.html", {'defaultDates':defaultDates, 'prevFilterIn':prevFilterIn, 'actualTable':actualTable, 'DbFailure':DbFailure})
so imagine my actualtable has a field 'News' that may or may not contain a link, e.g.:
'hello there, go to https://www.google.com/'
How do I manage the fact that I want in my template to have the same string printed out, but with the address actually being a link?
I will also extend this to non-addresses (say twitter hashtags by parsing text).
Should I act on views or templates?
I did try to go the views way:
I substitute the
'hello there, go to https://www.google.com/'
with
'hello there, go to https://www.google.com/'
But I get the actual tags printed out, which is not what I want...
Any ideas?
If you change it on the view, you need to print it with |safe on the template.
So it would be
{{table.column|safe}}, this way your link will be a link and not a string
I want to input the content of a text area and want to output it on another page but seems like there is nothing like multiline-text area in Flask. When I do the following
content = request.form['content']
it returns a string with line breaks as '\n' but when I try to output that content with replacing \n with or
, it doesn't seem to work.
So I thought I can store the multiline content in the form of a list.
So is there db column for the list, something like
content = db.Column(db.list(String))
or is there any other alternative.
Just to clarify, to the computer these 2 text examples are exactly equivalent:
myString = """Hello
World
"""
myString = "Hello\nWorld"
We can confirm this by checking the repr value for both versions
repr(myString)
# 'Hello\nWorld'
Whether or not the formatting is performed in a "friendly way" where the newlines are rendered as such, is entirely dependent on how you choose to display them. In HTML, newlines are denoted with a <br> tag, so one option would be to store the actual HTML-formatted string in your database after inserting them. However, this may pose a security hazard by either allowing malicious links to be made clickable, or by allowing Javascript snippets to be executed when rendering the page.
The simplest solution would be to use the HTML <pre> tag, which tells it that you have already handled the formatting ahead-of-time. Using the same myString value as before, we can display it nicely with
<pre>
{{ myString }}
<pre>
using the Jinja2 syntax, as long as we pass this string to the render_template function, for example
#app.route("/")
def index():
myString = "Hello\nWorld"
return render_template("index.html", myString=myString)
I have code like this `
celldata=""
count=0
for tableData in y:
count = count+1
strcount=str(count)
celldata += strcount + ")" + tableData .text + "\n"
return celldata
`
I am returning the value to be used in flask, the issue is I want each for loop row in a new line but after trying \n, and in the flask web app I am getting celldata in one single line with one space each between each output line of the for loop.
Here is my current output for celldata in flask web
1)xxxx 2)yyyy
I want the flask web url to return
1)xxxx
2)yyyy
You're presumably returning HTML, and viewing that HTML in a browser.
In HTML, all runs of whitespace are equivalent—there's no difference between '\n' and ' '. The browser should convert them all to single spaces, and then decide how to flow the results nicely.
So, you're going to have to learn some basic HTML. But here are a few quick hints to get you started:
<p>one paragraph</p> <p>another paragraph</p> defines two separate paragraphs.
<p>one paragraph<br />with a line break in the middle</p> defines a paragraph with a line break in the middle.
<table><tr><td>row one</td></tr> <tr><td>row two</td></tr></table> defines a table of two rows (and one column).
The last one is the most complicated, but given that you've got things named tableData and celldata, I suspect it may be what you actually want here.
HTML itself only specifies "structure", not layout. It's up to the browser to decide what "two paragraphs" or "a line break" or "two rows" actually means in terms of actual pixels. If you want finer control, you need to learn CSS as well as HTML, which lets you specify explicit styles for these elements.
If you are trying to format this as HTML, I would suggest you add <br /> also to the returned text:
celldata = []
for count, tableData in enumerate(y, start=1):
celldata.append('{}) {}<br/>'.format(count, tableData.text))
return '\n'.join(celldata)
This first builds a list of entries with the correct numbering, and then joins each line together with a newline. The newline is purely cosmetic and will only effect how the HTML appears when viewed as source. It is the <br /> which will ensure each entry appears on a different line.
enumerate() is used to automatically count your entries for you.
I have a web app that reads from the Tumblr API and reformats the way that "reblog chains" are formatted.
With Tumblr, commentary for a post is stored as HTML blockquotes. As users respond to the commentary above, another level gets added to the blockquote chain, eventually resulting in many nested reblog chains.
Here is an example of how a "reblog chain" looks in plain HTML:
<p><a class="tumblr_blog" href="http://chainsaw-police.tumblr.com/post/96158438802/example-tumblr-post">chainsaw-police</a>:</p><blockquote>
<p><a class="tumblr_blog" href="http://example-blog-domain.tumblr.com/post/96158384215/example-tumblr-post">example-blog-domain</a>:</p><blockquote>
<p>Here is an example of a Tumblr post.</p> <p>It can have multiple <p> elements sometimes. It may only have one, though, at other times.</p>
</blockquote>
<p>This is an example of a user “reblogging” a post. As you can see, the previous comment is stored above as a <blockquote>.</p>
</blockquote>
<p>This is another reblog. As you can see, all of the previous comments are stored as blockquotes, with earlier ones being residing deeper in the nest of blockquotes.</p>
And this is what it looks like when rendered.
I want to be able to reformat the reblog chain so that it looks more like this:
example-blog-domain:
Here is an example of a Tumblr post.
It can have multiple <p> elements sometimes. It may only have one, though, at other times.
chainsaw-police:
This is an example of a user “reblogging” a post. As you can see, the previous comment is stored above as a <blockquote>.
example-blog-domain:
This is another reblog. As you can see, all of the previous comments are stored as blockquotes, with earlier ones being residing deeper in the nest of blockquotes.
I know, It's an incredibly confusing structure, hence why I'm trying to write something to make it more readable.
Is there any way to interpret the HTML and split the reblogs up into individual "comments"? For example, having an array or dict that has the username and the commentary would be more than enough. However, after messing with lxml and BeautifulSoup for months, I'm at my wits' end.
If there was even a way to do it in CSS, which I highly doubt, that would be fine.
Thanks in advance, everyone!
I guess CSS does not have a such functionality.
You need parse to a structure by lxml, ... and render it. It is easier way. You can also create a filter using regexp that does not pass wrong items of html code.
reddit user /u/joyeusenoelle has answered my question over at /r/LearnPython using a tonne of convoluted regexes that end up looking more like a voodoo magic spell than a text manipulation script.
Lots of regexes later, I think I've solved this for an
arbitrarily-deep comment chain.
import re
with open("tcomment.txt","r") as tf:
text = ""
for line in tf:
text += line
tf.close()
text = text.replace("\n","")
text = text.replace(">",">\n")
text = text.replace("<","\n<")
text = re.sub("</p>\s*<p>","<br><br>", text)
text = text.replace("<p>\n", "")
text = text.replace("</p>\n","\n")
text = re.sub("<[/]{0,1}blockquote>","<chunk>",text)
text = re.sub("<a class=\"tumblr_blog\"[^>]+?>","<chunk>",text)
text = text.replace("</a>","")
text = re.sub("\n+","", text)
text = re.sub("\s{2,}"," ", text)
text = re.sub("<chunk>\s*<chunk>","<chunk>",text)
bits = text.split("<chunk>")
bits[0] = "Latest:"
comments = []
for i in range(len(bits)):
temp = ""
j = 0 - (i+1)
if (len(bits)-i) > i:
temp = "<b>" + bits[i] + "</b> " + bits[j]
comments.append(temp)
comments.reverse()
for comment in comments:
print("<p>%s</p>" % (comment))
print()
The line bits[0] = "Latest:" can be changed to whatever you want the
most recent comment to display, and you'll probably want to change how
the text comes into the script.
For the text you provided, this gives me:
<p><b>example-blog-domain:</b> Here is an example of a Tumblr post.<br><br>It can have multiple <p> elements sometimes. It may
only have one, though, at other times.
<p><b>chainsaw-police:</b> This is an example of a user "reblogging" a post. As you can see, the previous comment is stored
above as a <blockquote>.
<p><b>Latest:</b> This is another reblog. As you can see, all of the previous comments are stored as blockquotes, with earlier ones
being residing deeper in the nest of blockquotes.
e: Some thoughts: this is in Python 3, but everything but the print
statements should work in Python 2, I think. I used text.split()
whenever possible because direct string manipulation is typically
faster than regular expressions are, but that may not be appropriate
here. And finally, it's possible that I'm making more work for myself
than I need to in the substitutions section, but at this point I've
looked at the code too long to figure out if it could be slimmed down.
I am new to both Python (and django) - but not to programming.
I am having no end of problems with identation in my view. I am trying to generate my html dynamically, so that means a lot of string manipulation. Obviously - I cant have my entire HTML page in one line - so what is required in order to be able to dynamically build an html string, i.e. mixing strings and other variables?
For example, using PHP, the following trivial example demonstrates generating an HTML doc containing a table
<?php
$output = '<html><head><title>Getting worked up over Python indentations</title></head><body>';
output .= '<table><tbody>'
for($i=0; $i< 10; $i++){
output .= '<tr class="'.(($i%2) ? 'even' : 'odd').'"><td>Row: '.$i;
}
$output .= '</tbody></table></body></html>'
echo $output;
I am trying to do something similar in Python (in my views.py), and I get errors like:
EOL while scanning string literal (views.py, line 21)
When I put everything in a single line, it gets rid of the error.
Could someone show how the little php script above will be written in python?, so I can use that as a template to fix my view.
[Edit]
My python code looks something like this:
def just_frigging_doit(request):
html = '<html>
<head><title>What the funk<title></head>
<body>'
# try to start builing dynamic HTML from this point onward...
# but server barfs even further up, on the html var declaration line.
[Edit2]
I have added triple quotes like suggested by Ned and S.Lott, and that works fine if I want to print out static text. If I want to create dynamic html (for example a row number), I get an exception - cannot concatenate 'str' and 'int' objects.
I am trying to generate my html dynamically, so that means a lot of string manipulation.
Don't do this.
Use Django's templates. They work really, really well. If you can't figure out how to apply them, do this. Ask a question showing what you want to do. Don't ask how to make dynamic HTML. Ask about how to create whatever page feature you're trying to create. 80% of the time, a simple {%if%} or {%for%} does everything you need. The rest of the time you need to know how filters and the built-in tags work.
Use string.Template if you must fall back to "dynamic" HTML. http://docs.python.org/library/string.html#template-strings Once you try this, you'll find Django's is better.
Do not do string manipulation to create HTML.
cannot concatenate 'str' and 'int' objects.
Correct. You cannot.
You have three choices.
Convert the int to a string. Use the str() function. This doesn't scale well. You have lots of ad-hoc conversions and stuff. Unpleasant.
Use the format() method of a string to insert values into the string. This is slightly better than complex string manipulation. After doing this for a while, you figure out why templates are a good idea.
Use a template. You can try string.Template. After a while, you figure out why Django's are a good idea.
my_template.html
<html><head><title>Getting worked up over Python indentations</title></head><body>
<table><tbody>
{%for object in objects%}
<tr class="{%cycle 'even' 'odd'%}"><td>Row: {{object}}</td></tr>
{%endfor%}
</tbody></table></body></html>
views.py
def myview( request ):
render_to_response( 'my_template.html',
{ 'objects':range(10) }
)
I think that's all you'd need for a mockup.
In Python, a string can span lines if you use triple-quoting:
"""
This is a
multiline
string
"""
You probably want to use Django templates to create your HTML. Read a Django tutorial to see how it's done.
Python is strongly typed, meaning it won't automatically convert types for you to make your expressions work out, the way PHP will. So you can't concatenate strings and numbers like this: "hello" + num.