Reputation: 1074
I'm trying to nicely format some text data from database to send in emails in Django. I'm encountering some problems with strings with line breaks.
In particular,my desired output is:
1) t1 t2
t1_continue t2_end
t1_end
2) s1 s3
s1_continue
s1_end
Here the strings taken from database are "t1\nt1_continue\nt1_end", "t2\nt2_end", "s1\ns1_continue\ns1_end" and "s3".
This desired output is like what we see if we're having 3 columns in Excel.
What I want to say is that some strings contain line breaks so simple formatting such as:
print str(index) + '\t' + col1 + '\t' + col2
won't work.
Please share with me your approach.
Many thanks.
Upvotes: 2
Views: 2153
Reputation: 2016
I thought I could hack something together in a few minutes, but formatting text into columns is more difficult than I thought. However here is what I got so far, still pretty buggy...
class format_lines(object):
"""
1) some text goes 2nd column of text
here. But not its not really that
all text goes hard to add more text
in this column in a given format
2) another point
for text
"""
def __init__(self, *args, **kargs):
self.max_char_width = 30
self.gutter_width = 15
self.gutter = ' '*self.gutter_width
self.previous_line1 = None
self.previous_line2 = None
self.p1_index = 0
self.p2_index = 0
print args
print "len args = ", len(args)
if len(args) == 2:
print "Starting the test"
self.print_lines_(args[0], args[1])
def print_lines_(self, p1, p2):
while self.p1_index < len(p1.split()):
this = self.format_line_(p1, p2)
p1=this['p1']
p2=this['p2']
print this['line']
#problem with this format is it's going to messup words by
#pushing them to the next line (this could be fixed with a -
#or this function could be rewritten
def format_line_(self, p1, p2):
#must first figure out amount of words that can fit on a line
p1_words = [""]
p2_words = [""]
if p1:
p1_words = p1.split(' ')
p1_words = p1_words[self.p1_index:]
if p2:
p2_words = p2.split(' ')
p2_words = p2_words[self.p2_index:]
#format left side's output
loutput = p1_words[0]
if len(loutput) < self.max_char_width:
for i, word in enumerate(p1_words[1:]):
if (len(loutput) + len(word)) <= self.max_char_width:
loutput += (' {0}'.format(word))
self.p1_index = i
else:
break
self.p1_index+=1 #for loop iteration starts at index 1 not 0 so
#a +1 is required
elif (len(loutput) > self.max_char_width):
long_word = []
long_word.append(loutput[:len(loutput)/2])
long_word.append(loutput[len(loutput)/2:])
long_word[0]+='-'
p1_words[0]=long_word[0]
p1_words.insert(1, long_word[1])
p1 = ' '.join(p1_words)
else:
#the left output is a single word
#equal to the max_char_width
pass
#need to add 1 to the index, because at least 1 element in the list is
#going to be printed
self.p1_index+=1
#format right side's output
routput = p2_words[0]
if len(routput) < self.max_char_width:
for word in p2_words[1:]:
if (len(routput) + len(word)) <= self.max_char_width:
routput += (' {0}'.format(word))
else:
break
self.p2_index+=1
elif len(routput) > self.max_char_width:
long_word = []
long_word.append(routput[:len(routput)/2])
long_word.append(routput[len(routput)/2:])
long_word[0]+='-'
p2_words[0]=long_word[0]
p2_words.insert(1, long_word[1])
p2 = ' '.join(p2_words)
else:
#the right output is a single word
#equal to the max_char_width
pass
self.p2_index+=1
#determin gutter size
if len(loutput) < self.max_char_width:
loutput+=(' '*(self.max_char_width-len(loutput)))
#do not need to append spaces to the right hand size
output = ''
#if previous_line1 is not defined then there should be no way that previous_line2 is defined
if not self.previous_line1:
#must be the first line of a bullet point
output = '1){0}{1}{2}{3}'.format(self.gutter,
loutput,
self.gutter,
routput)
self.previous_line1 = loutput
self.previous_line2 = routput
else:
p1_width = len(self.previous_line1)
p2_width = len(self.previous_line2)
if loutput<p1_width:
loutput+=(' '*(len(self.previous_line1)-p1_width))
if routput<p2_width:
routput+=(' '*(len(self.previous_line2)-p2_width))
output = ' {0}{1}{2}{3}'.format(self.gutter,
loutput,
self.gutter,
routput)
ret_val = {'line':output, 'p1':(' '.join(p1_words)), 'p2':(' '.join(p2_words))}
return ret_val
if __name__ == '__main__':
t1 = "this is a very long line of text much larger than you can fit on one line"
t2 = "this is another long line, only this line is a little different from the first line"
test = format_lines(t2, t1)
Upvotes: 1
Reputation: 3184
You can use a <table>
to display tabular data in the email body.
Before the loop that print
s each table row, print
the table header:
print('<table>')
For each data row, format it like so:
print('<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>'.format(index, col1, col2))
Finally, after the loop that print
s each table row, print
the table footer:
print('</table>')
Upvotes: 1
Reputation: 311486
I think I understand what you're asking. You want to word-wrap text within a column, much like Excel can do if you have a block of text in a cell. I think this recipe will get you started; it appears to do pretty much what you want.
Upvotes: 0
Reputation: 5391
How \t
is displayed will differ by OS, application, ect. For true string formatting, I would recommend checking the docs. For your example,
print('{0}) {1:<25} {2}'.format(index,col1,col2))
Will do what you want, assuming that col1
is never larger than 24 characters. If it is, you can always adjust that value to your liking.
Upvotes: 3