Search code examples
pythonpython-2.7webapp2

On Verification Form Always Outputs "December" For Month: webapp2 and Google App Engine (Windows 7)


Doing the Udacity Intro to Backend course and learning basic webapp2. Relatively new to programming so I'll try to be clear. Using 64-bit Windows 7 Professional, if that matters.

One thing to note - I mostly use Python 3.6 (Anaconda) but am running 2.7 in a virtual environment. I'm not great with Python 2 and this is my first time using virtualenv.

I have a helloworld.py file which includes a class called MainPage that inherits from webapp2.RequestHandler and which contains function definitions for get and post. The file has an HTML form that asks a user to enter their birthday month, day, and year in three separate fields. There is also a submit button.

When the user enters their information, the validity of each the day, month, and year should be verified by a separate function (all three are in a separate module called verify_date). Each function basically checks that the information makes sense (no nonsense words or out-of-range dates). I am aware it doesn't enforce the differing lengths of months (eg Feb having only 28 days), but am not concerned with that.

1) If the user-entered information is valid ('January', '1', and '2000', for example) the page should accept the information and load a message that says, "Thanks for the Validation!" This works.

2) If any of the three pieces information is invalid, it should reload the form so that the user can re-enter everything. That's the issue. If I enter an out-of-range number for day or year, this works. But if I enter a made-up word into the "month" field, it A) loads the validation statement anyway, and B) writes "December" to the web page (I added a test statement) regardless of what is actually entered. For example, I could enter "April" into the box and it still prints "December." What's going on here?

NOTE: I tested the day/month/year verification functions independently in another IDE running Python 3.6, and they worked perfectly.

# helloworld.py

import webapp2
import verify_date

form = """
<form method="post">
    What is your birthday? 
    <br>

    <label>Month
        <input type="text" name ="month">
    </label>

    <label>Day
        <input type="text" name ="day">
    </label>

    <label>Year
        <input type="text" name ="year">
    </label>

    <br>
    <br>
    <input type="submit">
</form>

""" 

class MainPage(webapp2.RequestHandler):
    def get(self):
        #self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write(form)

    def post(self):

        user_month = verify_date.valid_month(self.request.get('month'))
        user_day = verify_date.valid_day(self.request.get('day'))
        user_year = verify_date.valid_year(self.request.get('year'))


        # Test: always prints what was actually entered in the field, 
        # as expected, even if it's gibberish
        self.response.out.write(self.request.get('month'))

        # Should return the month entered (capitalized by verify_date.valid_day)
        # Prints December, regardless of what's entered 
        self.response.out.write(user_month)

        # As expected, prints the entered day if in range. Reloads form otherwise
        self.response.out.write(user_day)

        # As expected, prints the entered day if in range. Reloads form otherwise
        self.response.out.write(user_year)

        if not(user_month and user_year and user_day):
            self.response.out.write(form)
        else:
            self.response.out.write("Thanks for the validation!")

        # Test: prints the entered month, even if gibberish
        self.response.out.write(self.request.get('month'))

app = webapp2.WSGIApplication([
    ('/', MainPage),
], debug=True)

# verify_date.py

def valid_month(month):
    months = ['January','February','March','April','May','June','July','August','September','October','November','December']
    months = [month.lower() for month in months]
    month = month.lower()

    if month in months:
        month = month[0].upper() + month[1::]
    else:
        print 'Sorry, that is a not a valid month.'
        month = None
    return month

def valid_day(day):
    if day.isdigit() and int(day) < 32 and int(day) > 0:
        day = int(day)
    else:
        day = None
    return day

def valid_year(year):
    if year.isdigit() and int(year) < 2021 and int(year) > 1899:
        year = int(year)
    else:
        year = None
    return year


Solution

  • Are you using python 2.x? I think your issue is related to this question: https://stackoverflow.com/a/4199355/2074794

    In python 2, the month variable in your list comprehension overrides the month arg passed to your function. So after the following line is executed, month holds the value of the last item in your months list, i.e. December:

    months = [month.lower() for month in months]

    You can use a different variable name there to avoid conflict:

    months = [m.lower() for m in months]