1#!/usr/bin/python2.5 2 3# Copyright (C) 2010 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); you may not 6# use this file except in compliance with the License. You may obtain a copy of 7# the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14# License for the specific language governing permissions and limitations under 15# the License. 16 17""" 18Defines Django forms for inserting/updating/viewing contact data 19to/from SampleSyncAdapter datastore. 20""" 21 22import cgi 23import datetime 24import os 25 26from google.appengine.ext import db 27from google.appengine.ext import webapp 28from google.appengine.ext.webapp import template 29from google.appengine.ext.db import djangoforms 30from model import datastore 31from google.appengine.api import images 32 33import wsgiref.handlers 34 35class BaseRequestHandler(webapp.RequestHandler): 36 """ 37 Base class for our page-based request handlers that contains 38 some helper functions we use in most pages. 39 """ 40 41 """ 42 Return a form (potentially partially filled-in) to 43 the user. 44 """ 45 def send_form(self, title, action, contactId, handle, content_obj): 46 if (contactId >= 0): 47 idInfo = '<input type="hidden" name="_id" value="%s">' 48 else: 49 idInfo = '' 50 51 template_values = { 52 'title': title, 53 'header': title, 54 'action': action, 55 'contactId': contactId, 56 'handle': handle, 57 'has_contactId': (contactId >= 0), 58 'has_handle': (handle != None), 59 'form_data_rows': str(content_obj) 60 } 61 62 path = os.path.join(os.path.dirname(__file__), 'templates', 'simple_form.html') 63 self.response.out.write(template.render(path, template_values)) 64 65class ContactForm(djangoforms.ModelForm): 66 """Represents django form for entering contact info.""" 67 68 class Meta: 69 model = datastore.Contact 70 71 72class ContactInsertPage(BaseRequestHandler): 73 """ 74 Processes requests to add a new contact. GET presents an empty 75 contact form for the user to fill in. POST saves the new contact 76 with the POSTed information. 77 """ 78 79 def get(self): 80 self.send_form('Add Contact', '/add_contact', -1, None, ContactForm()) 81 82 def post(self): 83 data = ContactForm(data=self.request.POST) 84 if data.is_valid(): 85 # Save the data, and redirect to the view page 86 entity = data.save(commit=False) 87 entity.put() 88 self.redirect('/') 89 else: 90 # Reprint the form 91 self.send_form('Add Contact', '/add_contact', -1, None, data) 92 93 94class ContactEditPage(BaseRequestHandler): 95 """ 96 Process requests to edit a contact's information. GET presents a form 97 with the current contact information filled in. POST saves new information 98 into the contact record. 99 """ 100 101 def get(self): 102 id = int(self.request.get('id')) 103 contact = datastore.Contact.get(db.Key.from_path('Contact', id)) 104 self.send_form('Edit Contact', '/edit_contact', id, contact.handle, 105 ContactForm(instance=contact)) 106 107 def post(self): 108 id = int(self.request.get('id')) 109 contact = datastore.Contact.get(db.Key.from_path('Contact', id)) 110 data = ContactForm(data=self.request.POST, instance=contact) 111 if data.is_valid(): 112 # Save the data, and redirect to the view page 113 entity = data.save(commit=False) 114 entity.updated = datetime.datetime.utcnow() 115 entity.put() 116 self.redirect('/') 117 else: 118 # Reprint the form 119 self.send_form('Edit Contact', '/edit_contact', id, contact.handle, data) 120 121class ContactDeletePage(BaseRequestHandler): 122 """Processes delete contact request.""" 123 124 def get(self): 125 id = int(self.request.get('id')) 126 contact = datastore.Contact.get(db.Key.from_path('Contact', id)) 127 contact.deleted = True 128 contact.updated = datetime.datetime.utcnow() 129 contact.put() 130 131 self.redirect('/') 132 133class AvatarEditPage(webapp.RequestHandler): 134 """ 135 Processes requests to edit contact's avatar. GET is used to fetch 136 a page that displays the contact's current avatar and allows the user 137 to specify a file containing a new avatar image. POST is used to 138 submit the form which will change the contact's avatar. 139 """ 140 141 def get(self): 142 id = int(self.request.get('id')) 143 contact = datastore.Contact.get(db.Key.from_path('Contact', id)) 144 template_values = { 145 'avatar': contact.avatar, 146 'contactId': id 147 } 148 149 path = os.path.join(os.path.dirname(__file__), 'templates', 'edit_avatar.html') 150 self.response.out.write(template.render(path, template_values)) 151 152 def post(self): 153 id = int(self.request.get('id')) 154 contact = datastore.Contact.get(db.Key.from_path('Contact', id)) 155 #avatar = images.resize(self.request.get("avatar"), 128, 128) 156 avatar = self.request.get("avatar") 157 contact.avatar = db.Blob(avatar) 158 contact.updated = datetime.datetime.utcnow() 159 contact.put() 160 self.redirect('/') 161 162class AvatarViewPage(BaseRequestHandler): 163 """ 164 Processes request to view contact's avatar. This is different from 165 the GET AvatarEditPage request in that this doesn't return a page - 166 it just returns the raw image itself. 167 """ 168 169 def get(self): 170 id = int(self.request.get('id')) 171 contact = datastore.Contact.get(db.Key.from_path('Contact', id)) 172 if (contact.avatar): 173 self.response.headers['Content-Type'] = "image/png" 174 self.response.out.write(contact.avatar) 175 else: 176 self.redirect(self.request.host_url + '/static/img/default_avatar.gif') 177 178class ContactsListPage(webapp.RequestHandler): 179 """ 180 Display a page that lists all the contacts associated with 181 the specifies user account. 182 """ 183 184 def get(self): 185 contacts = datastore.Contact.all() 186 template_values = { 187 'contacts': contacts, 188 'username': 'user' 189 } 190 191 path = os.path.join(os.path.dirname(__file__), 'templates', 'contacts.html') 192 self.response.out.write(template.render(path, template_values)) 193 194 195def main(): 196 application = webapp.WSGIApplication( 197 [('/', ContactsListPage), 198 ('/add_contact', ContactInsertPage), 199 ('/edit_contact', ContactEditPage), 200 ('/delete_contact', ContactDeletePage), 201 ('/avatar', AvatarViewPage), 202 ('/edit_avatar', AvatarEditPage) 203 ], 204 debug=True) 205 wsgiref.handlers.CGIHandler().run(application) 206 207if __name__ == '__main__': 208 main()