views:

55

answers:

3

I took an official example of Google App Engine, that creates a Shoppinglist, and modified it so it would:

Create two tables (contact and Phonenumber) instead of one Shoppinglist. This is to understand how google deals with two tables and the Foreignkey (see code below).

It displays everything until line 47:

data = PhoneNumber(data=self.request.POST) data2 = Contact(data2=self.request.POST)

Somehow it cant deal with the second "data2" object and gives me and error:

TypeError: init() got an unexpected keyword argument 'data2'

Why? What can I do to make it work?

Thanks for the time.

import cgi

from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app

from google.appengine.ext.db import djangoforms

class Contact(db.Model):
    name = db.StringProperty()
    birth_day = db.DateProperty()
    address = db.PostalAddressProperty()

class PhoneNumber(db.Model):
    contact = db.ReferenceProperty(Contact,
                                   collection_name='phone_numbers')
    phone_type = db.StringProperty(
        choices=('home', 'work', 'fax', 'mobile', 'other'))
    number = db.PhoneNumberProperty()

class PhoneNumberForm(djangoforms.ModelForm):
    class Meta:
        model = PhoneNumber

class ContactForm(djangoforms.ModelForm):
    class Meta:
        model = Contact

class MainPage(webapp.RequestHandler):
    def get(self):
        self.response.out.write('<html><body>'
                                '<form method="POST" '
                                'action="/">'
                                '<table>')
        # This generates our PhoneNumber, Contact list form and writes it in the response
        self.response.out.write(PhoneNumberForm())
        self.response.out.write(ContactForm())
        self.response.out.write('</table>'
                                '<input type="submit">'
                                '</form></body></html>')
    def post(self):
        #print self.request
        #print self.request.POST
        data = PhoneNumber(data=self.request.POST)
        data2 = Contact(data2=self.request.POST)
        if data.is_valid():
            # Save the data, and redirect to the view page
            entity = data.save(commit=False)
            entity.added_by = users.get_current_user()
            entity.put()
            self.redirect('/items.html')
        if data2.is_valid():
            # Save the data, and redirect to the view page
            entity = data2.save(commit=False)
            entity.added_by = users.get_current_user()
            entity.put()
            self.redirect('/items.html')
        else:
            # Reprint the form
            self.response.out.write('<html><body>'
                                    '<form method="POST" '
                                    'action="/">'
                                    '<table>')
            self.response.out.write(data)
            self.response.out.write(data2)
            self.response.out.write('</table>'
                                    '<input type="submit">'
                                    '</form></body></html>')

class ItemPage(webapp.RequestHandler):
    def get(self):
        query = db.GqlQuery("SELECT * FROM PhoneNumber ORDER BY name")
        for item in query:
            self.response.out.write('<a href="/edit?id=%d">Edit</a> - ' %
                                    item.key().id())
            self.response.out.write("%s - Need to buy %d, cost $%0.2f each<br>" %
                                    (item.name, item.quantity, item.target_price))

class EditPage(webapp.RequestHandler):
    def get(self):
        id = int(self.request.get('id'))
        item = Item.get(db.Key.from_path('Item', id))
        self.response.out.write('<html><body>'
                                '<form method="POST" '
                                'action="/edit">'
                                '<table>')
        self.response.out.write(PhoneNumberForm(instance=PhoneNumber))
        self.response.out.write(ContactForm(instance=Contact))
        self.response.out.write('</table>'
                                '<input type="hidden" name="_id" value="%s">'
                                '<input type="submit">'
                                '</form></body></html>' % id)
    def post(self):
        id = int(self.request.get('_id'))
        PhoneNumber = PhoneNumber.get(db.Key.from_path('PhoneNumber', id))
        Contact = Contact.get(db.Key.from_path('Contact', id))
        data = PhoneNumberForm(data=self.request.POST)
        data2 = ContactForm(data2=self.request.POST)
        if data.is_valid():
            # Save the data, and redirect to the view page
            entity = data.save(commit=False)
            entity.added_by = users.get_current_user()
            entity.put()
            self.redirect('/items.html')
        if data2.is_valid():
            # Save the data, and redirect to the view page
            entity = data2.save(commit=False)
            entity.added_by = users.get_current_user()
            entity.put()
            self.redirect('/items.html')
        else:
            # Reprint the form
            self.response.out.write('<html><body>'
                                    '<form method="POST" '
                                    'action="/">'
                                    '<table>')
            self.response.out.write(data)
            self.response.out.write(data2)
            self.response.out.write('</table>'
                                    '<input type="submit">'
                                    '</form></body></html>')

def main():
    application = webapp.WSGIApplication(
                                         [('/', MainPage),
                                          ('/edit', EditPage),
                                          ('/items.html', ItemPage),
                                          ],
                                         debug=True)

    run_wsgi_app(application)
if __name__=="__main__":
    main()
+1  A: 

I haven't used Django forms, but my guess would be something like this:

def post(self): 
    #print self.request 
    #print self.request.POST 
    data = PhoneNumberForm(data=self.request.POST) 
    data2 = ContactForm(data=self.request.POST) 
    if data.is_valid() and data2.is_valid(): 
        # Save the data, and redirect to the view page 
        entity = data.save(commit=False) 
        entity.added_by = users.get_current_user() 
        entity.put() 
        entity = data2.save(commit=False) 
        entity.added_by = users.get_current_user() 
        entity.put() 
        self.redirect('/items.html') 
    else: 
        # Reprint the form 
        self.response.out.write('<html><body>' 
                                '<form method="POST" ' 
                                'action="/">' 
                                '<table>') 
        self.response.out.write(data) 
        self.response.out.write(data2) 
        self.response.out.write('</table>' 
                                '<input type="submit">' 
                                '</form></body></html>') 

It is the form classes not the model classes which you need to create from self.request.POST.

These have an argument called data, not data2.

Saxon Druce
Thanks will try that!!
MacPython
Did not work. Errror:
MacPython
TypeError: __init__() got an unexpected keyword argument 'data2'
MacPython
@MacPython: Can you post your updated code which gives that error?
Saxon Druce
+1  A: 

You could actually simplify your code a bit.

class Contact(db.Model):
    name = db.StringProperty()
    birth_day = db.DateProperty()
    address = db.PostalAddressProperty()
    added_by = db.UserProperty(auto_current_user_add=True)

class PhoneNumber(db.Model):
    contact = db.ReferenceProperty(Contact,
                                   collection_name='phone_numbers')
    phone_type = db.StringProperty(
        choices=('home', 'work', 'fax', 'mobile', 'other'))
    number = db.PhoneNumberProperty()
    added_by = db.UserProperty(auto_current_user_add=True)

You don't need to add the current user in the form's save method, you can have appengine do it automatically.

In your def post(self): function, you shouldn't be instantiating the form with a data2 argument, that's invalid. I generally do something like this:

def post(self):
    form1 =  PhoneNumberForm(self.request.POST or None)
    form2 = Contact(self.request.POST or None)
    if form1.is_valid() and form2.is_valid():
        form1.save()
        form2.save()
    else:
        # re-display page....

There are two spots in your question where you are incorrectly passing 'data2' to the form's constructor (MainPage class and EditPage class), be sure to correct them both.

Aaron
A: 

This seemed to work for me Changed data = PhoneNumber(data=self.request.POST) data2 = Contact(data=self.request.POST) To data = PhoneNumberForm(data=self.request.POST) data2 = ContactForm(data=self.request.POST)


def post(self):
    #print self.request
    #print self.request.POST
    data = PhoneNumberForm(data=self.request.POST)
    data2 = ContactForm(data=self.request.POST)
    if data.is_valid():
        # Save the data, and redirect to the view page
        entity = data.save(commit=False)
        entity.added_by = users.get_current_user()
        entity.put()
        self.redirect('/items.html')
    if data2.is_valid():
        # Save the data, and redirect to the view page
        entity = data2.save(commit=False)
        entity.added_by = users.get_current_user()
        entity.put()
        self.redirect('/items.html')
    else:
        # Reprint the form
        self.response.out.write('<html><body>'
                                '<form method="POST" '
                                'action="/">'
                                '<table>')
        self.response.out.write(data)
        self.response.out.write(data2)
        self.response.out.write('</table>'
                                '<input type="submit">'
                                '</form></body></html>')
Allan