craftApprentice craftApprentice - 3 months ago 15
Python Question

Querying datastore: 'NoneType' object has no attribute

When I run this if block:

first_query = db.GqlQuery("SELECT * FROM Contract ORDER BY date DESC").get()
if first_query == None:
numBook = 42
numInitialPage = 42
numFinalPage = 42
first_record = Contract(book_number = 1, initial_page = 0, final_page = 0)
first_record.put()
contract = db.GqlQuery("SELECT * FROM Contract ORDER BY date DESC").get()
numBook = contract.book_number
numInitialPage = contract.final_page +1
numFinalPage = numInitialPage
else:
contract = first_query
numBook = first_query
numInitialPage = 51
numFinalPage = 51


The procedure jumps into the
if
block, but, then, I get this error message:

File "C:\Users\CG\Documents\udacity\contract\main.py", line 88, in get
numBook = contract.book_number
AttributeError: 'NoneType' object has no attribute 'book_number'


Since I used
.put()
to insert a record and
.get()
do acess it, why the value of contract is
None
?

Thanks in advance for any help!

Here the entire code:

# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import os

import webapp2

import jinja2

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

import re

from google.appengine.ext import db

USER_RE = re.compile(r"^[a-zA-Z0-9_ -]{3,20}$")
def valid_person(person):
return USER_RE.match(person)

PASS_RE = re.compile(r"^.{3,20}$")
def valid_SSN(SSN):
return PASS_RE.match(SSN)

EMAIL_RE = re.compile(r"^[\S]+@[\S]+\.[\S]+$")
def valid_email(email):
return EMAIL_RE.match(email)

import time

import datetime

def dateToday():
today = datetime.datetime.today()
todayDay = str(today.day)
todayMonth = str(today.month)
monthExt = {'1':' January ', '2':'February', '3':' March ', '4':'April', '5':'May', '6':'June', '7':' July ', '8':'August', '9':'September', '10':'October', '11':'November ', '12':'December'}
todayYear = str(today.year)
return(todayDay + ' of ' + monthExt[todayMonth] + ' of ' + todayYear)

class Person(db.Model):
firstName = db.StringProperty(required = True)
nacionality = db.StringProperty(required = True)
marital_status = db.StringProperty(required = True)
profession = db.StringProperty(required = True)
SSN = db.IntegerProperty(required = True)
driver_license = db.IntegerProperty(required = True)
# address = db.PostalAddress(required = False)

class Contract(db.Model):
book_number = db.IntegerProperty(required = True)
initial_page = db.IntegerProperty(required = True)
final_page = db.IntegerProperty(required = True)
## contrac_type = db.StringProperty(required = False, choices=set(["Purchase Agreement", "Rental House", "Rental Car"]))
## contract_place = db.StringProperty(required = False)
## contract_date = db.DateProperty (required = True, auto_now = True, auto_now_add = True)

class ContractingParty(db.Model):
person = db.ReferenceProperty(Person, required=True, collection_name="party_to_contracts")
condition = db.StringProperty(required = False, choices=set(["buyer", "seller", "renter", "owner", "witness"]))

class MainHandler(webapp2.RequestHandler):
def get(self):
first_query = db.GqlQuery("SELECT * FROM Contract ORDER BY date DESC").get()
if first_query == None:
numBook = 8
numInitialPage = 8
numFinalPage = 8
first_record = Contract(book_number = 1, initial_page = 0, final_page = 0)
first_record.put()
contract = db.GqlQuery("SELECT * FROM Contract ORDER BY date DESC").get()
numBook = contract.book_number
numInitialPage = contract.final_page +1
numFinalPage = numInitialPage
else:
contract = first_query
numBook = first_query
numInitialPage = 7
numFinalPage = 7

## numBook = contract.book_number
## numInitialPage = contract.final_page +1
## numFinalPage = numInitialPage
template_values = {"person": "",
"nacionality": "",
"SSN": "",
"driverLicense": "",
"email":"",
"person_error": "",
"SSN_error": "",
"driverLicense_error": "",
"address": "",
"email_error": "",
"numBook": numBook,
"numInitialPage": numInitialPage,
"numFinalPage": numFinalPage,
}
template = jinja_environment.get_template('index.html')
self.response.out.write(template.render(template_values))

def post(self):
person_name = self.request.get("person")
user_nacionality = self.request.get('nacionality')
user_profession = self.request.get('profession')
user_maritalStatus = self.request.get('maritalStatus')
user_SSN = self.request.get('SSN')
user_email = self.request.get('email')
user_driverLicense = self.request.get('driverLicense')
person_error = ""
SSN_error = ""
driverLicense_error = ""
geted_email_error = ""
address = self.request.get('address')
contractType = self.request.get("contractType")
owner = self.request.get("owner")
witness = self.request.get("witness")
numBook = self.request.get("numBook")
numInitialPage = self.request.get("numInitialPage")
numFinalPage = self.request.get("numFinalPage")

if (person_name and valid_person(person_name)) and (user_SSN and valid_SSN(user_SSN)) and ((not user_email) or (user_email and valid_email(user_email))):
contract_record = Contract(book_number = numBook, initial_page = numInitialPage, final_page = numFinalPage)
contract_record.put()
contract_id = contract_record.key().id()
person_record = Person(name = person_name,
nacionality = user_nacionality,
profession = user_profession,
marital_status = user_maritalStatus,
SSN = int(user_SSN),
driverLicense = int(user_driverLicense))
person_record.put()
# HERE THE PROBLEM - Contracting party should be a table with ID refering to contract table
# contracting_party_record = ContractingParty(person = 1, )
## person = db.ReferenceProperty(People, required=True, collection_name="party_to_contracts")
## condition = db.StringProperty(required = False, choices=set(["buyer", "seller", "renter", "owner", "witness"]))
## self.redirect('/your_contract?person=%s&nacionality=%s&profession=%s&maritalStatus=%s&SSN=%s&driverLicense=%s&email=%s&witness=%s&owner=%s&contractType=%s&address=%s&numBook=%s&numInitialPage=%s&numFinalPage=%s' % (person_name, user_nacionality, user_profession, user_maritalStatus, user_SSN, user_driverLicense, user_email,
##witness, owner, contractType, address, numBook, numInitialPage, numFinalPage))
self.redirect('/your_contract?person=%s' % contract_id)

else:
if not person_name or not valid_person(person_name):
person_error = "Oh no!!! this person name isn't valid!"
if not user_SSN or not valid_SSN(user_SSN):
SSN_error = "Oh no!!! SSN isn't valid!"
if user_email and not valid_email(user_email):
geted_email_error = "Oh no!!! e-mail isn't valid!"
template_values = {"person": person_name,
"nacionality": user_nacionality,
"maritalStatus": user_maritalStatus,
"profession": user_profession,
"SSN": user_SSN,
"driverLicense": user_driverLicense,
"email": user_email,
"person_error": person_error,
"SSN_error": SSN_error,
"driverLicense_error": user_driverLicense,
"address": address,
"email_error": geted_email_error}
template = jinja_environment.get_template('index.html')
self.response.out.write(template.render(template_values))

class your_contractHandler(webapp2.RequestHandler):
def get(self):
contract_id = self.request.get('contract_id')
contract = db.GqlQuery("SELECT * FROM Contract WHERE __key__ = KEY('Model', contract_id").get()
## SELECT * FROM Model where __key__ = KEY('Model', <numeric_id>)
geted_numBook = contract.book_number
geted_numInitialPage = contract.initial_page
geted_numFinalPage = contract.final_page
geted_dateToday = dateToday()
geted_contractType = contract.contract_type

person = db.GqlQuery("SELECT * FROM Person ORDER BY date DESC").get()
geted_person_name = person.name
geted_user_nacionality = person.nacionality
geted_user_profession = person.profession
geted_user_maritalStatus = person.marital_status
geted_user_SSN = person.SSN
geted_user_driver_license = person.driver_license


your_contract = jinja_environment.get_template('your_contract.html')

your_contract_values = {"person":geted_person_name,
"nacionality":geted_user_nacionality,
"maritalStatus": geted_user_marital_status,
"profession": geted_user_profession,
"SSN":geted_user_SSN,
"driverLicense":geted_user_driver_license,
"address":geted_address,
"email":geted_user_email,
"contractType":geted_contract_type,
"dateContract":geted_dateToday,
"numBook":geted_numBook,
"numInitialPage":geted_numInitialPage,
"numFinalPage":geted_numInitialPage,
}
template = jinja_environment.get_template('index.html')
self.response.out.write(your_contract.render(your_contract_values))


# ContractingParty.all().ancestor(thecontract).run()
# contract_id = contract.key().id()
# contract_parties = Contract.get_by_id(contract_id)
#http://stackoverflow.com/questions/11294526/how-to-model-a-contract-database-with-several-buyers-or-sellers-using-gae-data
#http://stackoverflow.com/questions/11311461/how-to-query-gae-datastore-to-render-a-template-newbie-level
app = webapp2.WSGIApplication([('/', MainHandler), ('/your_contract', your_contractHandler)],
debug=True)

Answer

Because you don't have a date field in your Contract model, so nothing is returned.

Because the datastore is schemaless, GQL can't know whether or not any of the entities in your model might have a particular field. So, unlike SQL, it doesn't raise an error when you reference a non-existent field: it just performs the query, and if nothing is found, it returns nothing.

I'm not sure why you want to query it in any case. And even if you did, you should really get it by the key that's returned from the put() call, rather than doing a query: the eventual consistency model means that it's possible for the data not to be fully persisted by the next statement, so a query wouldn't see it whereas a direct get by key is always guaranteed to do so.