我是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)
AttributeError:'博客'对象没有属性'post_content'
我认为博客需要继承 db_blog ,所以(参见#2)
AttributeError:'NoneType'对象没有属性'replace'
我认为错误告诉我,我正在传递一个不存在的对象,所以我真的很困惑。如果我注释掉试图替换“\ n”字符的行,这段代码运行完美 - 那么它怎么能不传递对象呢?或声称它是==无?
更重要的是,我怎样才能让它发挥作用!
非常感谢你读到这一点,以及能够让我前进的财富王国。
答案 0 :(得分:1)
您收到属性错误的原因是因为self
中的Newpost.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 %}
你需要使用上面的安全,因为否则jinja将逃脱你的<br />
。由于我看不到你的模板,我不知道这是否完全适合你的工作,但希望你能明白这一点。
解释上面三行的jinja:
{% for post in query_select %}
- 就像for循环一样,遍历帖子,每个帖子应该是db_blog
个实例(来自您的查询)。post.escaped_content
完全等同于在Python中调用db_blog模型的escaped_content
属性。{{ post.escaped_content | safe }}
将safe
过滤器应用于转义内容生成的字符串(不包含safe
,jinja会将<br />
转换为<br />
(这将显示页面上的<br />
。{% 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))
对不起文字的墙 - 希望有些东西在那里很有用!