Search code examples
pythonangularjsgoogle-app-enginewebapp2

GAE posting an array to the datastore with Python (One to Many)


Been workining with GAE for a few months. It's my first time working with One-to-Many relationships here. Everything has been posting all well to the datastore until I started with relationships. This is the first one. Could someone please help me with this 'post' to datastore? The docs and other examples are quite confusing for now. I know I'm doing it incorrectly by employees=r['Employees'], I just want a simple post first. If you could plunker it even better! I am getting a BadValueError upon posting as shown;

enter image description here

model.py

class Project(ndb.Model):
    projectID = ndb.IntegerProperty(required=True)
    title = ndb.StringProperty(required=True)
    description = ndb.StringProperty(required=True)
    startAt = ndb.DateTimeProperty(indexed=True)
    endAt = ndb.DateTimeProperty()
    employees = ndb.KeyProperty(kind='Employees', repeated=True)

class Employees(ndb.Model):
    name = ndb.StringProperty()
    role = ndb.StringProperty()

handlers.py

 def post(self):
    r = json.loads(self.request.body) 
    print str(r)

    g = Project(projectID=int(r['ProjectID']),  
                description=r['Description'],
                title=r['Title'],
                employees=r['Employees'],
                startAt=datetime.strptime(r['StartAt'], '%d/%m/%Y %H:%M %p'),
                endAt=datetime.strptime(r['EndAt'], '%d/%m/%Y %H:%M %p'))

    project_key = g.put()
    project_key.get()
    print project_key

controller.js

    $scope.employees = [
                            {
                                name:'mark',
                                role: 'dev'
                            }, 
                            {
                                name:'colin',
                                role: 'dev2'
                            }, 
                       ];

UPDATE----------------------------------------------------------------------

json handler

class commentsJsonHandler(webapp2.RequestHandler):
@classmethod
def route(cls):
    """
    name: index, template: /
    """
    return webapp2.Route('/comments', handler=cls, name='_commments_')


def get(self):  
    recommendations = Project.query()

    def date_handler(obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        else:
            raise TypeError

    self.response.out.write(json.dumps([dict(rec.to_dict(), **dict(id=rec.key.id())) for rec in recommendations], default=date_handler))

Solution

  • You have to iterate over the employees collection in your json payload and create those Employee entities first and use their keys to create the Project entity

    def post(self):
        r = json.loads(self.request.body)
        print str(r)
        employee_keys = []
        for emp in r['Employees']:
            employee = Employees(name=emp['name'], role=emp['role'])
            employee.put()
            employee_keys.append(employee.key)
    
    
        g = Project(projectID=int(r['ProjectID']),
                    description=r['Description'],
                    title=r['Title'],
                    employees=employee_keys,
                    startAt=datetime.strptime(r['StartAt'], '%d/%m/%Y %H:%M %p'),
                    endAt=datetime.strptime(r['EndAt'], '%d/%m/%Y %H:%M %p'))
    
        project_key = g.put()
        project_key.get()
        print project_key