通过python在谷歌应用引擎中创建多对多关系数据库

时间:2011-08-24 11:41:27

标签: python database google-app-engine

我试图建立3个数据库;人,事件和爱好。每个人从提供的列表中选择业余爱好数据库中的业余爱好。当一个人创建一个事件时,该人选择将该事件标记为哪个爱好。从那里,活动邀请将被发送给选择该爱好的人。该活动将使用Google Calendar API进行.... 我坚持制作这个3数据库,并尝试使用关系属性或列表属性来关联它们...环顾四周但不太好编程所以我有点卡住... 如果有人能帮助我,我会非常感激。

class Hobby(db.Model):
name = db.StringProperty()

@property
def members(self):
    return Person.all().filter('hobby', self.key())

h1 = Hobby(key_name ='key1', name = 'tennis')
h2 = Hobby(name = 'basketball')
h1.put()
h2.put()

class Person(db.Model):
name = db.StringProperty()
hobby = db.ListProperty(db.Key)


p1 = Person(name = 'tom', hobby = Hobby.get_by_key_name(['key1']))
p1.put()


class Event(db.Model):
title = db.StringProperty(required=True)
description = db.TextProperty()
time = db.DateTimeProperty()
location = db.TextProperty()
creator = db.UserProperty()
edit_link = db.TextProperty()
gcal_event_link = db.TextProperty()
gcal_event_xml = db.TextProperty()
hobby = db.ListProperty(db.Key)

@property
def members(self):
    return Person.all().filter('event', self.key())





class Attendee(db.Model):
  email = db.StringProperty()
  event = db.ReferenceProperty(Event)
  hobby = db.ReferenceProperty(Hobby)



class Greeting(db.Model):
  author = db.UserProperty()
  content = db.StringProperty(multiline=True)
  date = db.DateTimeProperty(auto_now_add=True)





class BasePage(webapp.RequestHandler):
  title = ''

def write_page_header(self):
self.response.headers['Content-Type'] = 'text/html'
self.response.out.write('<html><head><title>%s</title>'
'<link href="static/invitations.css" rel="stylesheet" type="text/css"/>'
'</head><body><div id="main">' % (
    self.title,))
self.write_signin_links()



def write_signin_links(self):
if users.get_current_user():
  template_values = {
      'signed_in': True,
      'user_link': users.create_logout_url('/')}
else:
  template_values = {
      'signed_in': False,
      'user_link': users.create_login_url('/events')}
path = os.path.join(os.path.dirname(__file__), 'templates')
path = os.path.join(path, 'signin.html')
self.response.out.write(template.render(path, template_values))

def write_page_footer(self):
self.response.out.write('</div></body></html>')


class StartPage(BasePage):
  title = 'One Macnica'

  def get(self):
  self.write_page_header()
  template_values = {'sign_in': users.create_login_url('/events')}
  path = os.path.join(os.path.dirname(__file__), 'templates')
path = os.path.join(path, 'start.html')
self.response.out.write(template.render(path, template_values))
self.write_page_footer()


class EventsPage(BasePage):
 title = 'One Macnica'

 def __init__(self):
# Create a Google Calendar client to talk to the Google Calendar service.
self.calendar_client = gdata.calendar.service.CalendarService()
# Modify the client to search for auth tokens in the datastore and use
# urlfetch instead of httplib to make HTTP requests to Google Calendar.
gdata.alt.appengine.run_on_appengine(self.calendar_client)

def get(self):
"""Displays the events the user has created or is invited to."""
self.write_page_header()

# Find all events which this user has created, and find events which this
# user has been invited to.
invited_events = []
owned_events = []
token_request_url = None

# Find an AuthSub token in the current URL if we arrived at this page from
# an AuthSub redirect.
auth_token = gdata.auth.extract_auth_sub_token_from_url(self.request.uri)
if auth_token:
  self.calendar_client.SetAuthSubToken(
      self.calendar_client.upgrade_to_session_token(auth_token))

# Check to see if the app has permission to write to the user's
# Google Calendar.
if not isinstance(self.calendar_client.token_store.find_token(
        'http://www.google.com/calendar/feeds/'),
    gdata.auth.AuthSubToken):
  token_request_url = gdata.auth.generate_auth_sub_url(self.request.uri,
     ('http://www.google.com/calendar/feeds/',))


query_time = self.request.get('start_time')
# TODO handle times provided in the URL.
if not query_time:
  query_time = datetime.datetime.now()

# Find the events which were created by this user, and those which the user
# is invited to.
if users.get_current_user():
  owned_query = Event.gql('WHERE creator = :1 ORDER BY time',
      users.get_current_user())
  owned_events = owned_query.fetch(5)

  invited_query = Attendee.gql('WHERE email = :1',
      users.get_current_user().email())
  for invitation in invited_query.fetch(5):
    try:
      invited_events.append(invitation.event)
    except db.Error, message:
      if message[0] == 'ReferenceProperty failed to be resolved':
        # The invitee has an invitation to an event which no longer exists.
        pass
      else:
        raise

template_values = {
    'token_request_url': token_request_url,
    'owned_events': owned_events,
    'invited_events': invited_events,
     }



# Display the events.
path = os.path.join(os.path.dirname(__file__), 'templates')
path = os.path.join(path, 'events.html')
self.response.out.write(template.render(path, template_values))
self.write_page_footer()


def post(self):
"""Adds an event to Google Calendar."""
event_id = self.request.get('event_id')

# Fetch the event from the datastore and make sure that the current user
# is an owner since only event owners are allowed to create a calendar
# event.
event = Event.get_by_id(long(event_id))



if users.get_current_user() == event.creator:
  # Create a new Google Calendar event.
  event_entry = gdata.calendar.CalendarEventEntry()
  event_entry.title = atom.Title(text=event.title)
  event_entry.content = atom.Content(text=event.description)
  if start_time is None:
    start_time = '%s.000Z' % event.time.isoformat()
    end_time = '%s.000Z' % event.time.isoformat(time.time()+3600)
  event_entry.when.append(gdata.calendar.When(start_time=start_time, end_time=end_time))
  event_entry.where.append(
      gdata.calendar.Where(value_string=event.location))
  # Add a who element for each attendee.
  attendee_list = event.attendee_set
  if attendee_list:
    for attendee in attendee_list:
      new_attendee = gdata.calendar.Who()
      new_attendee.email = attendee.email
      event_entry.who.append(new_attendee)

 #Adding hobby for each attendee
"""hobby_list = event.hobby_set
  if hobby_list:
    for hobby in hobby_list:
        new_hobby = gdata.calendar.ExtendedProperty()
        new_hobby.name = hobby.name
        event_entry.extended_property.append(new_hobby)
        """

 # Hobby to which a person belongs:
p = db.get(person_key)
hobby = db.get(p.hobby) #batch get using list of keys
for hobby in hobby:
        new_hobby = gdata.calendar.ExtendedProperty()
        new_hobby = hobby.name
        event_entry.extended_property.append(new_hobby)


#Person that belong to a hobby:
h = db.get(hobby_key)
for person in h.members:
        new_person = gdata.calendar.Who()
        new_person.name = person.name
        event_entry.who.append(new_person)



# Event to which a person belongs:
p = db.get(person_key)
event = db.get(p.event)
for event in event:
        new_event = gdata.calendar.ExtendedProperty()
        new_event = event.title
        event_entry.extended_property.append(new_event)

# Person that belong to a event:
e = db.get(event_key)
for person in e.members:
        new_person = gdata.calendar.Who()
        new_person.name = person.name
        event_entry.who.append(new_person)



  # Send the event information to Google Calendar and receive a
  # Google Calendar event.
try:
    cal_event = self.calendar_client.InsertEvent(event_entry,
        'http://www.google.com/calendar/feeds/default/private/full')
    edit_link = cal_event.GetEditLink()
    if edit_link and edit_link.href:
      # Add the edit link to the Calendar event to use for making changes.
      event.edit_link = edit_link.href
    alternate_link = cal_event.GetHtmlLink()
    if alternate_link and alternate_link.href:
      # Add a link to the event in the Google Calendar HTML web UI.
      event.gcal_event_link = alternate_link.href
      event.gcal_event_xml = str(cal_event)
    event.put()
  # If adding the event to Google Calendar failed due to a bad auth token,
  # remove the user's auth tokens from the datastore so that they can
  # request a new one.
except gdata.service.RequestError, request_exception:
    request_error = request_exception[0]
    if request_error['status'] == 401 or request_error['status'] == 403:
      gdata.alt.appengine.save_auth_tokens({})
    # If the request failure was not due to a bad auth token, reraise the
    # exception for handling elsewhere.
    else:
      raise
else:
  self.response.out.write('I\'m sorry, you don\'t have permission to add'
                          ' this event to Google Calendar.')

# Display the list of events also as if this were a get.
self.get()

我发布了一些代码。我之后编辑了事件类等,但我认为它在解决数据库情况时并不重要......

提前感谢任何帮助或建议。

1 个答案:

答案 0 :(得分:0)

创建Person实体的问题在于上面(在第1页)您尝试将Hobby实体分配给Person.hobby,该实体应该是一个Hobby键列表(和可能被称为爱好)

h = Hobby(name='basketball')
h_key = h.put() # or after h.put(), h.key()
p = Person(name='tom', hobbies=[h_key])
p.put()

此外,您的Person模型没有属性event,因此Event.members将失败。

除了这些之外,使用db.ListProperty()是处理多对多关系的正确方法,这些关系不包含其他信息。