2011-10-27 150 views
1

我想從數據庫中很好地格式化一些文本數據以便在Django中的電子郵件中發送。我遇到與換行符字符串的一些問題。Python格式化帶換行符的字符串

特別是,我的期望的輸出是:

1) t1      t2 
    t1_continue   t2_end 
    t1_end 

2) s1      s3 
    s1_continue 
    s1_end 

在這裏從數據庫中獲取的字符串是 「T1 \ nt1_continue \ nt1_end」, 「T2 \ nt2_end」, 「S1 \ ns1_continue \ ns1_end」 和「S3 」。

這個所需的輸出就像我們看到的,如果我們在Excel中有3列。

我想要說的是,某些字符串包含換行符這麼簡單的格式,如:

print str(index) + '\t' + col1 + '\t' + col2 

將無法​​正常工作。

請與我分享你的做法。

非常感謝。

+0

我不知道你問什麼,但如果你追加一個逗號','打印功能也不會增加一個換行符。 '打印「測試」,'。 – Griffin

+1

如果你做了一個'print(col1)',輸出是否爲't1t1_continuet1_end'?換句話說,你是否想要在給定的列中包裝文本? – brc

+0

你好brc,出來會是t1 \ nt1_continue \ nt1_end。我也編輯了這個問題,使其更清晰。謝謝。 –

回答

1

您可以使用<table>在電子郵件正文中顯示錶格數據。

之前的循環,print s各自錶行,print表頭:

print('<table>') 

對於每個數據行,格式它像這樣:

print('<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>'.format(index, col1, col2)) 

最後,循環,print後s每桌排,print桌腳:

print('</table>') 
3

如何顯示\t將根據操作系統,應用程序等而有所不同。對於真正的字符串格式,我建議檢查docs。對於你的榜樣,

print('{0}) {1:<25} {2}'.format(index,col1,col2)) 

會做你想要什麼,假設col1是從來沒有超過24個字符。如果是這樣,您可以隨時根據自己的喜好調整該值。

+0

僅當電子郵件有等寬字體時纔有效... – Don

+0

好點,我不太確定這將解決問題無論如何,一旦問題得到澄清,我會進行適當的編輯。 – brc

0

我想我明白你在問什麼。你想在文本中對文本進行文字換行,就像Excel在單元格中有文本塊時可以做的那樣。我認爲this recipe會讓你開始;它似乎做了你想要的東西。

1

我以爲我可以在幾分鐘內把東西拼湊在一起,但將文本格式化爲列比我想象的要困難得多。但是這裏是我到目前爲止,仍然相當越野車...

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)