Manas Chaturvedi
Manas Chaturvedi

Reputation: 5540

Google App Engine: Retrieving data from database

I am trying to build a simple blog application to use the skills that I learned from Udacity so far. However, I am having trouble retrieving data from the database and displaying it for the user. Now, my blog has a permalink which displays the post that was just being submitted by the user, and also the main blog page which will display the latest 10 posts in descending order. But when I submit a post, the post is stored in the database successfully, and I am being redirected to a permalink. However, all I get is a blank page instead of the post that I just submitted.

Also, when I go back to my main blog page, I see this instead of all the posts being submitted by the user:

enter image description here

Here's the main python code:

import os
import re
import webapp2
import jinja2
from string import letters
from google.appengine.ext import db

template_dir = os.path.join(os.path.dirname(__file__), 'templates')
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir),     autoescape=True)

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

class Handler(webapp2.RequestHandler):
    def write(self, *a, **kw):
        self.response.out.write(*a, **kw)

    def render_str(self, template, **params):
        return render_str(template, **params)

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

def render_post(response, post):
    response.out.write('<b>' + post.subject + '</b><br>')
    response.out.write(post.content)

def post_key(name = "dad"):
    return db.Key.from_path('blog', name)

class Blogger(db.Model):
    name = db.StringProperty()
    content = db.TextProperty()
    created = db.DateTimeProperty(auto_now_add = True)

    def render(self):
        self._render_text = self.content.replace('\n', '<br>')
        return render_str("post.html", p = self)

class MainPage(Handler):
    def get(self):
        self.response.write("Visit our blog")

class BlogHandler(Handler):
    def get(self):
        posts = db.GqlQuery("SELECT * FROM Blogger order by created desc")
        self.render("frontblog.html", posts = posts)    

class SubmitHandler(Handler):
    def get(self):
        self.render("temp.html")    
    def post(self):
        name = self.request.get("name")
        content = self.request.get("content")
        if name and content:
            a = Blogger(parent = post_key(), name = name, content = content)
            a.put()
            self.redirect('/blog/%s' % str(a.key().id()))
        else:
            error = "Fill in both the columns!"
            self.render("temp.html", name = name, content = content, error = error)        

class DisplayPost(Handler):
    def get(self, post_id):
        post_id = self.request.get("post_id")
        if post_id:
            po = Blogger.get_by_id(int(post_id), parent = post_key())
            if po:
                self.render("perma.html", po = po)   
            self.response.write("No")  


app = webapp2.WSGIApplication([('/', MainPage),
                          ('/blog', BlogHandler), 
                          ('/blog/submit', SubmitHandler),
                          (r'/blog/<post_id:([0-9]+)>', DisplayPost)], debug=True)

Here's the HTML code for the base of all the HTML pages:

<!DOCTYPE html>
<html>
<head>
  <link type="text/css" rel="stylesheet" href="/static/main.css" />

  <title>CS 253 Blog</title>
</head>

<body>
  <a href="/blog" class="main-title">
    CS 253 Blog
  </a>

  <div id="content">
  {% block content %}
  {% endblock %}
  </div>
</body>

</html>

Here's the HTML code for the permalink page:

{% extends "base.html" %}

{% block content %}
  {{po.render() | safe}}
{% endblock %}

HTML code for the front of the blog:

{% extends "base.html" %}

{% block content %}

  {% for p in posts %}
    {{ p.render() | safe }}
    <br><br>
  {% endfor %}

{% endblock %}

I have been struggling with this for over two days now. I see no bugs in the logs either. What seems to be the problem?


EDIT:

Edited the source code based on the answers below. However, I still get a 404 error.

Upvotes: 0

Views: 310

Answers (1)

Josh
Josh

Reputation: 603

You are creating your Blogger entity with a parent key that you are not specifying when you are trying to retrieve your post in your DisplayPost.

An entity's key is composed of multiple parts. It's Kind ("Blogger"), it's ID (int(post_id)), and also it's ancestor, or parent.

Because you create your entity with:

a = Blogger(parent = post_key(), name = name, content = content)

You need to specify the same parent when calling get_by_id() (see the get_by_id() docs).

Your solution will be to change

po = Blogger.get_by_id(int(post_id))

to

po = Blogger.get_by_id(int(post_id), parent=post_key())

Later, if you change the name of the blog (looking at the code for post_key()), then you'll need to carry that as an argument to the post display mechanism. (You might use a subdomain as the 'name' of the blog for example).


Here is the previous answer that addressed issues with the regex URL mapping:

In your WSGIApplication definition, you have ('/blog/([0-9]+)', DisplayPost)], debug=True).

You are missing the r before the url string to identify the string as a regular expression:

(r'/blog/([0-9]+), ....

You also have the option to be more verbose with parameter naming:

(r'/blog/<post_id:([0-9]+)>, ....

Reference: http://webapp-improved.appspot.com/guide/routing.html

Upvotes: 1

Related Questions