Rebecca Rebecca - 3 months ago 9
Python Question

User input in Python is not being written to database

Just for fun, I'm creating a website in Python and using the Google Datastore to create a website that lets users post a movie title and a review for the movie. I am also using Jinja2 templating. The problem is, the

movie_name
gets written to the databases on all occasions except one, which is in the class that says
MoviePage
. It seems like that is the only class that isn't reading the variable
movie_name
, not even the jinja template is reading that variable. However, I have other variables in my html that are being parsed by jinja2, it's only that one variable I'm having trouble with. Here is my code:

class MovieReviews(db.Model):
movie_name = db.StringProperty()
review = db.TextProperty(required = True)
created = db.DateTimeProperty(auto_now_add = True)
last_modified = db.DateTimeProperty(auto_now = True)

class MoviesOnWebsite(db.Model):
movie_name = db.StringProperty(required = True)
created = db.DateTimeProperty(auto_now_add= True)



class AddMovie(StrHandler):
def get_front(self,movie_name="",error=""):
add_movie = db.GqlQuery("SELECT * FROM MoviesOnWebsite")
self.render("add-movie.html",movie_name=movie_name,error=error,add_movie=add_movie)

def get(self):
self.get_front()

def post(self):
haveError = False
movie_name = self.request.get("movie_name")

params = dict(movie_name=movie_name)

if not movie_name:
params['error_movie_name'] = "Must write movie name"
haveError = True
if haveError:
self.render("add-movie.html", **params)
self.response.out.write('You have errors')
else:
addmovie = MoviesOnWebsite(movie_name=movie_name)
addmovie.put()
site_url = urllib.urlencode(dict(movie_name=movie_name))
self.redirect('/' + site_url)

class MoviePage(StrHandler):
def get_front(self, review="",error=""):
addmovie = AddMovie()
full_url = addmovie.site_url
movie_reviews = db.GqlQuery("SELECT * FROM MovieReviews")
self.render("movie_review_page.html", review=review,error=error,movie_reviews=movie_reviews)

def get(self,url):
self.get_front()

def post(self,url):
path = urlparse.urlparse(full_url).path
movie_name = self.request.get('movie_name')
review = self.request.get("review")

if review:
movie_rev = MovieReviews(path = path,review = review)
movie_rev.put()

else:
error = "You haven't submitted a review"
self.get_front(review,error)


And a small code snippet from my html page called
movie_review_page.html
to verify that the jinja syntax is correct:

<body>
<h1>{{movie_name}}</h1>
....


I'll explain what my code is doing. The classes
MovieReviews
and
MoviesOnWebsite
are just database models. The class
AddMovie
lets a user add a movie to the database if no one has ever submitted a review for that particular movie. After the user adds the movie name to the database, they get redirected to a url that looks like this:
www.websitename.com/nameOfMovie
. And from there, the class
MoviePage
has a form that lets users add a movie title and a review and adds it to the database. The problem as I mentioned before, when a user adds a movie title and review in the
MoviePage
class, only the review gets written to the database and the movie title is blank. The movie title that I want written to the database is the movie the user is doing a review for, namely, the name of the movie found in the url. The
movie_name
only gets written to the database in the class
AddMovie
. And the url with the path that has the name of the movie also works. The problem is in the
MoviePage
class. I should mention that
add-movie.html
has a textbox with the name
movie_name
and
movie_review_page.html
does not. If I change the variable from
movie_name = self.request.get('movie_name')
to
movie_name="abcd"
then abcd gets written to the database, but it doesn't work the other way around.

I'd appreciate any help.

Answer

I am not sure what web framework you are using but the issue seems to be caused by query parameters vs url paramters.

The other values are included in the form and therefor retrieved successfully from self.request.get. For movie_name you can't use the same call, you will need to extract it from the current url somehow, but this will cause problems if your movie has non standard characters in it or spaces.

Rather url encode the parameter and include it in the redirect:

Change the redirect to this:

import urllib
self.redirect('/?' + urllib.urlencode(dict(movie_name=movie_name))

The generated url should look like /?movie_name=The%20Terminator

Then retrieve the data like so:

self.request.get("movie_name")