2

我是 Python、Google AppEngine 和 Jinja 的新手。如果我在下面发布了太多代码,我很抱歉。这是我向 StackOverflow 发布的第一个问题。

我正在构建一个博客(为一个班级),我需要在用户的帖子中替换换行符“\n”。查询数据库的函数将其结果发送到 render() 函数。

在我添加应该替换“\n”的代码行之前,所有代码都可以正常工作。

我进行了各种编辑,但我无法推断 AppEngine、Jinja 或 Python 要我做什么来满足它。

我的数据库类设置了四种类型的 db_blog 类型,包括“ post_content

class db_blog(db.Model):
    post_subject = db.StringProperty(required = True)
    post_content = db.TextProperty(required = True)
    post_created = db.DateTimeProperty(auto_now_add = True)
    post_last_modified = db.DateTimeProperty(auto_now_add = True)

'Newpost' 类我希望它从下面的Blog类中接收 ' query_select ' 对象。

class Newpost(webapp2.RequestHandler):
    def write(self, *args, **kwds):
        self.response.out.write(*args, **kwds)

    def render_str(self, template, **params):
        t = jinja_env.get_template(template)
        return t.render(params)

    def render(self, template, **kwds):
        self._render_text = self.post_content.replace("\n", "<br />") ##<-- See here 
        self.write(self.render_str(template, **kwds))

Blog 类获取所有用户帖子并将它们发送到“Newpost”以进行呈现。

class Blog(Newpost):
    def get(self):
        query_select = db.GqlQuery("SELECT * FROM db_blog ORDER BY post_created DESC")
        self.render('blog_posts.htm', query_select = query_select)

1 、如上图,代码会产生这个错误:

AttributeError:“博客”对象没有属性“post_content”

我认为类Blog需要从db_blog继承,所以(见#2)

2. 如果我将db_blog添加到Blog类的参数列表中,我会收到一个新错误:

AttributeError:“NoneType”对象没有“替换”属性

我认为错误告诉我我正在传递一个不存在的对象,所以我真的很困惑。如果我注释掉试图替换“\n”字符的行,这段代码运行完美——那么它怎么能不传递对象呢?或者声称它==无?

更重要的是,我怎样才能让它工作!

非常感谢你读到这里,感谢他/她的财富王国,让我继续前进。

4

2 回答 2

1

在我写这篇文章的时候,@JeffTratner 提出了一个很好的建议,让替换成为你模型的属性。我绝对支持这是一个很好的解决方案,所以希望这只会帮助您了解正在发生的事情:)


欢迎!我会先说我没有使用过 jinja(也不是任何类型的 GAE 专家),所以我会尝试专注于我认为导致您的问题的原因(其他更聪明的人会很快纠正我)。

错误

当您使用 Gql 查询数据存储时,结果是可迭代的。在您的代码中,query_select是这些可迭代对象之一,其中每个项目都是具有db_blog您指定的四个属性的实体。(注意:您可能会更改db_blogBlog[样式约定等],无论如何我都会建议以后摆脱该类:))

看起来您正在尝试用<br>'s 替换任何换行符,为此您正在调用replace方法 on self.post_content。问题self在于这个上下文是一个Blog实例,它与你真正想要的完全不同(这将是 中的项目query_select)。编辑: JeffTratner 的方法比我以前的方法好,所以我删除了我所拥有的,并假设你按照他的建议设置了你的模型 :) 在这种情况下,你可以简单地运行你的查询,然后将结果传递给模板:

query_select = db.GqlQuery("SELECT * FROM db_blog ORDER BY post_created DESC")
self.write(self.render_str(template, **kwds))

关键要点 - 查询数据存储将 [几乎] 总是返回一个可迭代的。因此,如果您想对返回的数据做其他事情,您将不得不迭代您的结果:

query_select = db.GqlQuery("SELECT * FROM db_blog ORDER BY post_created DESC")
for result in query_select:
    # Do stuff...

结构

对此持保留态度,因为我不确定您的意图是什么,但是有没有理由Blog是它自己的课程?我在 Newpost 中没有看到get方法 - 是否曾经直接访问过?如果没有,您是否可以通过完全删除Blog并将get方法移入来实现相同的功能Newpost

class Newpost(webapp2.RequestHandler):
    def get(self):
        query_select = db.GqlQuery("SELECT * FROM db_blog ORDER BY post_created DESC")
        self.render('blog_posts.htm', query_select = query_select)

    def write(self, *args, **kwds):
        self.response.out.write(*args, **kwds)

    def render_str(self, template, **params):
        t = jinja_env.get_template(template)
        return t.render(params)

    def render(self, template, **kwds):
        self.write(self.render_str(template, **kwds))

这种结构意味着所有get调用都Newpost将查询数据存储并呈现结果(不需要单独的类)。另外,这可能是因为我不熟悉 jinja,但似乎您可以将 // 方法压缩render为一个render_strwrite但我想可以等待,因为它现在正在工作:) )。如果您想尝试,这是一种完全未经测试(而且很可能是错误的)的方法:

class Newpost(webapp2.RequestHandler):
    def get(self):
        query_select = db.GqlQuery("SELECT * FROM db_blog ORDER BY post_created DESC")
        self.render('blog_posts.htm', query_select = query_select)

    def render(self, template, **kwds):        
        t = jinja_env.get_template(template)
        self.response.out.write(t.render(**kwds))

对不起,文字墙 - 希望那里有一些有用的东西!

于 2012-08-23T04:43:03.800 回答
1

您收到属性错误的原因是selfinNewpost.get指的是RequestHandler( Blog) 而不是您想要的帖子。我建议不要在视图函数中定义转换,而是将其添加为模型的属性,例如

class db_blog(db.Model):

    post_subject = db.StringProperty(required = True)
    post_content = db.TextProperty(required = True)
    post_created = db.DateTimeProperty(auto_now_add = True)
    post_last_modified = db.DateTimeProperty(auto_now_add = True)

    @property
    def escaped_content(self):
        # possibly want to escape HTML in your post_content first
        return self.post_content.replace("\n", "<br />")

然后,您可以传递query_select给您的模板(就像您现在所做的那样):

{% for post in query_select %}
{{ post.escaped_content | safe }}
{% endfor %}

你需要在上面使用 safe,否则 jinja 会逃脱你的<br />. 由于我看不到你的模板,我不知道这是否完全符合你正在做的事情,但希望你明白这一点。

解释上面三行神器:

  1. {% for post in query_select %}- 就像 for 循环一样,遍历帖子,每个帖子都应该是一个db_blog实例(来自您的查询)。
  2. post.escaped_content完全等同于escaped_content在 Python 中调用 db_blog 模型的属性。
  3. {{ post.escaped_content | safe }}safe过滤器应用于转义内容产生的字符串(没有safe,jinja 将转换<br />&lt;br /&gt;(将在页面上逐字显示<br />)。
  4. {% endfor %}结束 for 循环。
于 2012-08-23T04:19:02.433 回答