Becky S
Becky S

Reputation: 83

'AttributeError: 'NoneType' object has no attribute 'to_dict'

I am developing an API using Google App Engine in Python. I am having trouble sending a GET request to a particular url. I get the 'NoneType' object has no attribute to_dict error. The trouble comes in at out = client.to_dict() in the apiClient.py, which is routed to in main.py by

app.router.add(webapp2.Route(r'/api/client/<clientid:[0-9]+><:/?>', 'apiClient.Client'))

I do not understand why ndb.Key(db_defs.Client, int(kwargs['clientid'])).get() is returning None

apiClient.py:

import webapp2 
from google.appengine.ext import ndb
import db_defs
import json

class Client(webapp2.RequestHandler):
    #returns all or a specified client(s)
    def get(self, **kwargs):
        if 'application/json' not in self.request.accept:
            self.response.status = 406
            self.response.status_message = "Not acceptable: json required"
            return
        if 'clientid' in kwargs:
            client = ndb.Key(db_defs.Client, int(kwargs['clientid'])).get()
            out = client.to_dict()
            self.response.write(json.dumps(out))
        else:
            q = db_defs.Client.query()
            keys = q.fetch(keys_only=True)
            results = { 'keys' : [x.id() for x in keys]}
            self.response.write(json.dumps(results))

db_defs.py:

from google.appengine.ext import ndb

#http://stackoverflow.com/questions/10077300/one-to-many-example-in-ndb

class Model(ndb.Model):
    def to_dict(self):
        d = super(Model, self).to_dict()
        d['key'] = self.key.id()
        return d

class Pet(Model):
    name = ndb.StringProperty(required=True)
    type = ndb.StringProperty(choices=set(["cat", "dog"]))
    breed = ndb.StringProperty(required=False)
    weight = ndb.IntegerProperty(required=False)
    spayed_or_neutered = ndb.BooleanProperty()
    photo = ndb.BlobProperty()
    owner = ndb.KeyProperty(kind='Client')


class Client(Model):
    lname = ndb.StringProperty(required=True)
    fname = ndb.StringProperty(required=False)
    phone = ndb.StringProperty(required=False)
    email = ndb.StringProperty(required=False)
    staddr = ndb.StringProperty(required=False)
    pets = ndb.KeyProperty(kind='Pet', repeated=True, required=False)

    def to_dict(self):
        d = super(Client, self).to_dict()
        d['pets'] = [p.id() for m in d['pets']]
        return d

EDIT:

When I do a GET request to http://localhost:8080/api/client/ I get a list of client ids:

{"keys": [4679521487814656, 4855443348258816, 5136918324969472, 5242471441235968, 5277655813324800, 5559130790035456, 5699868278390784, 5805421394657280, 6051711999279104, 6368371348078592, 6544293208522752, 6614661952700416, 6685030696878080]}

which I have verified are the same as those present in the GAE Datastore Viewer.

But when I do a GET request to http://localhost:8080/api/client/4679521487814656 I get the NoneType Error.

Upvotes: 0

Views: 7653

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121924

client is set to None, which is not an object with a to_dict() method.

client is None because the following expression returned None:

client = ndb.Key(db_defs.Client, int(kwargs['clientid'])).get()

e.g. there is no Client object with that key.

Upvotes: 1

Related Questions