如何替换Google Datastore查询结果对象中的字符?

时间:2012-08-23 03:25:02

标签: python google-app-engine inheritance scope jinja2

我是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'

我认为博客需要继承 db_blog ,所以(参见#2)

2。如果我将 db_blog 添加到博客类'参数列表中,则会出现新错误:

AttributeError:'NoneType'对象没有属性'replace'

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

更重要的是,我怎样才能让它发挥作用!

非常感谢你读到这一点,以及能够让我前进的财富王国。

2 个答案:

答案 0 :(得分:1)

您收到属性错误的原因是因为self中的Newpost.get引用了RequestHandlerBlog)而不是你想要的帖子。我建议,不要在视图函数中定义转换,而是将其作为模型的属性添加,例如

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 %}

你需要使用上面的安全,因为否则jinja将逃脱你的<br />。由于我看不到你的模板,我不知道这是否完全适合你的工作,但希望你能明白这一点。

解释上面三行的jinja:

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

答案 1 :(得分:1)

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


欢迎!我将通过说我没有使用过jinja(也不是任何一种GAE专家)作为序言,所以我会尝试专注于我认为导致你的问题(而其他更聪明的人会很快纠正我)。

错误

使用Gql查询数据存储区时,结果是可迭代的。 在您的代码中,query_select是其中一个iterables,其中每个项目都是db_blog实体,具有您指定的四个属性。 (注意:您可以将db_blog更改为Blog [样式约定等],我建议稍后再删除该类:))

看起来你要做的就是用<br>替换任何换行符,为此你在replace上调用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_str / write方法压缩成一个,但我猜这可以等待因为它现在正在工作:))。如果你想尝试,这是一个完全未经测试(很可能是错误的),可能的方式:

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))

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