在用户提交的内容中呈现换行符(Python Web应用程序)

时间:2012-07-06 05:12:23

标签: python html jinja2 web.py

我有一个web.py应用程序,它从textarea获取输入并将其输入到数据库。我可以从数据库中获取信息并将其发布到页面,但NEWLINES已经消失。在回发到HTML时,如何保留换行符?数据中包含\r\n但在HTML中不会呈现为NEWLINES。有什么想法吗?这是一个小例子:

(2, u'Title', u'content here...hey\r\nthis\r\nhas\r\nbreaks in it....?', 
    datetime.datetime(2012, 7, 5, 21, 5, 14, 354516))

这是我从数据库中返回的。我需要\r\n代表<br />,如果有两个<p>则会很棒。任何方向都会非常感激。

还有一个图书馆吗?我听说过markdown和mark up但是我找不到如何从python字符串发布html数据的例子?

4 个答案:

答案 0 :(得分:10)

两种主要方法。最简单的方法是将输出包装在<pre></pre>中,并将其格式化为输入。

或者,您可以使用<br />(而不是<p>)替换新内容,因为字符代表换行符而非段落。

对于第二种选择,这是一种方法:

>>> s
'hello\nthere\r\nthis\n\ris a test'
>>> r = '<br />'
>>> s.replace('\r\n',r).replace('\n\r',r).replace('\r',r).replace('\n',r)
'hello<br />there<br />this<br />is a test'
>>> 

或者第三个选项 - 使用众多文本条目库/格式之一并通过它们呈现内容(如其他人所提到的那样 - 如markdown)。

但是,如果您只想做一个简单的替换,那就太过分了。

答案 1 :(得分:6)

新行未呈现为换行符是html中的预期行为。你想要的是插入<br>或将你的输入解析为文本段落并用<p>包裹那些.. </p>

我会混合使用两者:对于单个换行符使用<br>,对于双换行符使用<p> .. </p>。您可以在保存到数据库时或在将其保存时进行解析。

编辑:我为您制作了以下图片。有很多方法可以查看解析器。就个人而言,我想将它们视为一种状态机。为了实现它,您应该以流方式读取输入字符串,例如使用http://docs.python.org/library/stringio.html

enter image description here Edit2:将描述“下推自动机”更改为“状态机”。下推自动机是正确但不精确的,它与图形不匹配 - 我将两者混合起来。

Edit3:这里有一些关于如何在代码中实现状态机解析器的sudo代码,使用while循环,switch case和if语句进行状态转换。

state = 'plainState'
streamer = get_stream_reader_from_input()
buffer = ''
while true {
  nextchar = streamer.readchar()
  if (nextchar == null) { //EOS
   print(buffer)
   exit
  }
  switch (state) {
    case('plainState') {
      if (nextchar == '\n') {
        state = 'singleBreakState' 
      }
      else if (nextchar == '\r') {
        state = 'CRState'
      }
      else {
        buffer += nextchar
      }
    }
    case('singleBreakState') {
      if (nextchar == '\n') {
        state = 'doubleBreakState' 
      }
      else if (nextchar == '\r') {
        state = 'CRState2'
      }
      else {
        state = 'plainState'
        buffer += '<br>' + nextchar
      }
    }
    //...
  }
}  

答案 2 :(得分:3)

在提出解决方案之前,您需要对发生的事情有一些基本的了解。如果你不理解这个问题,那么“扔进另一个图书馆”的方法要么根本不能工作(更好),要么很快就会适得其反(更糟)。

@MichelMüller在说明HTML源代码中的\n未在浏览器中呈现时是正确的。有关此行为的更详细说明,请参阅this tutorial(caveat,HTML 2.0描述)。现在,要在HTML中添加换行符,请使用<br>;添加一个新段落<p>

你可以做很多事情来实现这个目标,但是你要解决的问题是什么?这个用户提交的内容是什么?谁提交了它?需要考虑的两个方面是:

  1. 格式即可。是对公共网站的评论,还是网站工作人员或UGC在Stack Overflow等网站上发布的帖子?
  2. 安全即可。它是由陌生人发布的,还是由完全信任的用户发布的,还是设置在中间?
  3. 可能的解决方案:

    • 最直接的方法是在将text.replace('\r\n', '<br>')输出到模板格式化程序之前运行它。如果你没有在模板中放置{ text | safe },那么将无效,因为Jinja不应该逃脱你生成的<br>。但是,文本本身不应该完全信任,因此您必须在替换换行符之前转义<&(至少)

    • 查看MarkupSafe,了解处理HTML转义的不那么特别的方法。顺便说一句,它被Jinja聘用。

    • 要格式化非结构化内容(即用户提交的评论 a la YouTube),请查看PottyMouth库。

    • 如果您的内容准备得更充分(在博客平台或类似Stack Overflow的网站上发布),请按照@BernhardKircher的建议尝试Markdown。它有一些学习曲线,因此如果用户愿意花一些时间写帖子,它会效果最好。请记住正确配置解析器,因为核心Markdown不会转义HTML

    • 对于员工准备的内容,您可以使用Markdown或其他更复杂的内容。这真的取决于员工的背景。在这里,未转义的HTML可能是一种祝福,而不是一种诅咒。

答案 3 :(得分:2)

您可以使用像markdown这样的格式化语言(如您所述),而不是使用不是html的插入文本,因此不会显示为html(\ r \ n不是“p”标签等) 。

否则你需要手动替换/解析输入的文本(我认为这不是一个好主意,因为像这样的语言已经被发明了。)

有一些好的python库可以将 markdown (你存储在数据库中的数据)转换成html,比如python-markdown2

它非常易于使用,请参阅python-markdown链接中的示例:

>>> import markdown2
>>> markdown2.markdown("*boo!*")  # or use `html = markdown_path(PATH)`
u'<p><em>boo!</em></p>\n'

>>> markdowner = Markdown()
>>> markdowner.convert("*boo!*")
u'<p><em>boo!</em></p>\n'
>>> markdowner.convert("**boom!**")
u'<p><strong>boom!</strong></p>\n'

这会强制您使用markdown语法(或您使用的任何格式)输入内容。为了使这更容易,您可以使用所见即所得编辑器为您创建降价(就像Stackoverflow上的编辑器一样)。 我认为Stackoverflow使用wmd,但还有很多其他降价的所见即所得编辑。

wmd的示例:

<html>
    <head>
        <title>WMD Example using jquery</title>
        <link rel="stylesheet" type="text/css" href="wmd.css"/>

        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
        <script type="text/javascript" src="jquery.wmd.min.js"></script>
    </head>
    <body>
        <h1>WMD Example using jquery</h1>
        <div>
            <textarea id="notes"/>
        </div>

        <script type="text/javascript">
            $().ready(function() {
               $("#notes").wmd(); 
            });
        </script>
    </body>
</html>