How To Build A Personal Portal On Google App Engine With Django

14,638 views

Published on

Speaker: Jimmy Lu
Topics: How To Build A Personal Portal On Google App Engine With Django
Date: 2010.02.19

WECO Lab, CSIE, FJU

Published in: Technology
4 Comments
5 Likes
Statistics
Notes
  • Hey jimmy Lu,
    Can you please check out my GAE website : http://www.cloudeasyfileshare.appspot.com/

    I am not able to understand the error. Please help me.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dear Jimmy Lu,
    I can't read the file http://sls.weco.net/files/u233/jimmylu-portal.rar (with ZIP), can you help me?
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Thanks for leaving a comment. You can download the source code here: http://sls.weco.net/files/u233/jimmylu-portal.rar, and modify the personal info to get your own personal portal.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • hello. this is pretty neat but it seems to be missing a lot of stuff. is the full source code anywhere?
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
14,638
On SlideShare
0
From Embeds
0
Number of Embeds
1,382
Actions
Shares
0
Downloads
88
Comments
4
Likes
5
Embeds 0
No embeds

No notes for slide

How To Build A Personal Portal On Google App Engine With Django

  1. 1. ……… WECO Seminar Part II How to build a personal portal on Google App Engine with Django Speaker : Jimmy Lu Advisor : Hsing Mei Web Computing Laboratory Computer Science and Information Engineering Department Fu Jen Catholic University
  2. 2. Outline • Design your personal portal • Environment settings  main.py  settings.py  app.yaml • Implementation • Demo • Q&A WECO Lab, CSIE dept., FJU March 2, 2010 2 http://www.weco.net
  3. 3. Design your personal portal • What elements should a personal portal have?  Text: a simple blog - An editor - Posts archive  Photos: upload and resize a profile picture  Videos: fetch latest video you upload to your Youtube channel by Youtube API and embed it  Widgets: embed Google Calendar and WECO Lab, CSIE dept., FJU March 2, 2010 3 Google Map http://www.weco.net
  4. 4. Environment settings (1/5)  main.py 1. import os 2. # point to seetings.py, then django knows how to configure the en vironment 3. os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' 4. 5. from google.appengine.ext.webapp.util import run_wsgi_app 6. from google.appengine.dist import use_library 7. 8. # use_library('library_name', 'version'), impot django library 9. use_library('django', '1.1') WECO Lab, CSIE dept., FJU March 2, 2010 4 http://www.weco.net
  5. 5. Environment settings (2/5) 10. 11. # django has implemented WSGI 12. import django.core.handlers.wsgi 13. 14. def main(): 15. # Create a Django application for WSGI. 16. application = django.core.handlers.wsgi.WSGIHandler() 17. 18. # Run the WSGI CGI handler with that application. 19. run_wsgi_app(application) 20. 21. 22. if __name__ == '__main__': 23. main() WECO Lab, CSIE dept., FJU March 2, 2010 5 http://www.weco.net
  6. 6. Environment settings (3/5)  settings.py import os # Because the django database mapping is not work on Google App Engine, we need to leave the database settings empty. DATABASE_ENGINE = '' DATABASE_NAME = '' DATABASE_USER = '' DATABASE_PASSWORD = '' DATABASE_HOST = '' DATABASE_PORT = '‘ # localization TIME_ZONE = 'Asia/Taipei’ LANGUAGE_CODE = 'zh-TW ' WECO Lab, CSIE dept., FJU March 2, 2010 6 http://www.weco.net
  7. 7. Environment settings (4/5) # The path of the project root directory. ROOT_PATH = os.path.dirname(__file__) # Set the path where your templates locate. TEMPLATE_DIRS = ( ROOT_PATH + '/templates', ) INSTALLED_APPS = ( # 'django.contrib.contenttypes', # 'django.contrib.sessions', ) # Leave the others default. WECO Lab, CSIE dept., FJU March 2, 2010 7 http://www.weco.net
  8. 8. Environment settings (5/5) • app.yaml  Define the mapping of path to directory of static files(stylesheets, images, etc.) and the url.  handlers:  - url: /stylesheets  static_dir: static/stylesheets  - url: .*  script: main.py WECO Lab, CSIE dept., FJU March 2, 2010 8 http://www.weco.net
  9. 9. Implementation – models (1/2) • models.py  We define three classes to store posts and pictures. 1. class BlogPost(db.Model): 2. author = db.StringProperty() 3. title = db.StringProperty() 4. body = db.TextProperty() 5. # add the current time automatically. 6. timestamp = db.DateTimeProperty(auto_now_add = True) 7. 8. # a django form related to BlogPost. 9. class BlogPostForm(djangoforms.ModelForm): 10. class Meta: March 11. model = BlogPost Lab, CSIE dept., FJU WECO 2, 2010 9 http://www.weco.net
  10. 10. Implementation – models (2/2) 12. 13.class Picture(db.Model): 14. # use BlobProperty to store a photo. 15. profilePicture = db.BlobProperty() 16. timestamp = db.DateTimeProperty(auto_now_add = True) WECO Lab, CSIE dept., FJU March 2, 2010 10 http://www.weco.net
  11. 11. Implementation – views (1/8) • views.py  Define a function to have an ability to edit a blog post and save it to the database. 1. def edit(request): 2. # Use django form API, we can build a form object and display a form easily. 3. blogPostForm = BlogPostForm(data = request.POST or None) 4. t = loader.get_template("edit.html") 5. c = Context({ 'blogPostForm': blogPostForm }) 6. blogPost = None 7. if blogPostForm.is_valid(): WECO Lab, CSIE dept., FJU March 2, 2010 11 http://www.weco.net
  12. 12. Implementation – views (2/8) 8. # Save the BlogPost object without save it to the databas e(commit = False). 9. blogPost = blogPostForm.save(commit = False) 10. if blogPost: 11. # Save it to the database. 12. blogPost.put() 13. if request.POST: 14. # Redirect to the main page. 15. return http.HttpResponseRedirect('/') 16. 17. return HttpResponse(t.render(c)) WECO Lab, CSIE dept., FJU March 2, 2010 12 http://www.weco.net
  13. 13. Implementation – views (3/8)  Define a function to upload profile pictures. Notice that we use images API to resize the uploaded images. 1. def upload(request): 2. if request.method == 'POST': 3. picture = Picture() 4. # Resize the picture by images API provided by Google App engine. 5. profile_picture = images.resize(request.FILES['img'].read (), 196, 196) 6. picture.profilePicture = db.Blob(profile_picture) 7. picture.put() 8. return http.HttpResponseRedirect('/') 9. WECO Lab, CSIE dept., FJU March 10. 2, 2010 return render_to_response('upload.html') 13 http://www.weco.net
  14. 14. Implementation – views (4/8)  When a browser renders main.html, it will send request to the image source. By using url mapping, we map the url request to this function. 1. def image(request): 2. # Get the picture by the key from database. 3. picture = Picture.get(request.GET['img_id']) 4. # Build your response 5. response = HttpResponse(picture.profilePicture) 6. # Set the content type to png because that's what the Google images api stores modified images as by default 7. response['Content-Type'] = 'image/png' 8. 9. return response WECO Lab, CSIE dept., FJU March 2, 2010 14 http://www.weco.net
  15. 15. Implementation – views (5/8)  Use urlfetch API to fetch the response(XML format) from Youtube API and parse it to a DOM object. Then we can get the video id under “entry” elements. 1. def video(request): 2. # From Youtube API document, you can get the url for getting your uploaded video. 3. url = "http://gdata.youtube.com/feeds/api/users/gn00023040/up loads" 4. # Fetch the result from url by urlfetch API provided by Googl e App engine. 5. result = urlfetch.fetch(url) 6. id = '' WECO Lab, CSIE dept., FJU March 2, 2010 15 http://www.weco.net
  16. 16. Implementation – views (6/8) 7. if result.status_code == 200: 8. # Parse the XML format by minidom which is a python build- in library. 9. xmldoc = minidom.parseString(result.content) 10. # An entry represents a video. 11. videos = xmldoc.getElementsByTagName('entry') 12. if videos: 13. # Get the first(latest) entry. 14. latest_video = videos[0] 15. id = latest_video.childNodes[0].childNodes[0].data[42:] 16. 17. return id WECO Lab, CSIE dept., FJU March 2, 2010 16 http://www.weco.net
  17. 17. Implementation – views (7/8) • Send parameters to the templates to display post archive, profile picture, latest video and widgets. 1. def main(request): 2. # Get all the posts chronologically. 3. posts = BlogPost.all().order('-timestamp') 4. # Store some parameters by Context dictionary. 5. c = Context() 6. c['posts'] = posts 7. c.push() 8. # Get the latest picture. 9. pictures = Picture.all().order('-timestamp').fetch(1) WECO Lab, CSIE dept., FJU March 2, 2010 17 http://www.weco.net
  18. 18. Implementation – views (8/8) 1. if pictures: 2. picture = pictures[0] 3. c['image_key'] = picture.key() 4. c.push() 5. # Request to the video function. 6. video_id = video(request) 7. if video_id != '': 8. c['id'] = video_id 9. c.push() 10. # Load the template. 11. t = loader.get_template("main.html") 12. 13. # Send the parameters to the template, then the template will process the result. 14. return HttpResponse(t.render(c)) WECO Lab, CSIE dept., FJU March 2, 2010 18 http://www.weco.net
  19. 19. Implementation – templates (1/6) • edit.html  {{blogPostForm}} display a form for editing a blog post. 1. <form action="{%url views.edit%}" method="post"> 2. <table> 3. <!-- Display the form by django's form API --> 4. {{blogPostForm}} 5. <tr> 6. <td><input type="submit" value="Post"></td> 7. </tr> 8. </table> 9. </form> WECO Lab, CSIE dept., FJU March 2, 2010 19 http://www.weco.net
  20. 20. Implementation – templates (2/6) • upload.html  Make sure the enctype attribute should be multipart/from-data 1. <!-- Remember the enctype attribute of the form shold by multipart/fr om-data or request.FILES will receive nothing. --> 2. <form action="{%url views.upload%}" method="post" enctype="multip art/form-data"> 3. <input type="file" name="img" /> 4. <input type="submit" value="Upload" /> 5. </form> WECO Lab, CSIE dept., FJU March 2, 2010 20 http://www.weco.net
  21. 21. Implementation – templates (3/6) • main.html  Extend base.html and display post archive. 1. {% extends "base.html" %} 2. {% block content %} 3. <!-- Display all the posts iteratively --> 4. {% for post in posts %} 5. <h2>{{ post.title }}</h2> 6. <p>{{ post.timestamp|date:"l, F jS" }}</p> 7. <p>{{ post.body }}</p> 8. {% endfor %} 9. {% endblock %} WECO Lab, CSIE dept., FJU March 2, 2010 21 http://www.weco.net
  22. 22. Implementation – templates (4/6) • base.html  Map the src=“image?img_id=…” to the image function and get the image id by request.GET[„image_id‟] 1. <h2>My Picture</h2> 2. <!-- If there is no profile picture, we will ask for one. --> 3. {% if image_key %} 4. <!-- Django will map the url, 'image?img_id=...', to the image functi on and get the image_key by requets.GET --> 5. <img src="image?img_id={{ image_key }}"></img> 6. {% else %} 7. Click <a href="upload">here</a> to upload your profile picture! 8. {% endif %} WECO Lab, CSIE dept., FJU March 2, 2010 22 http://www.weco.net
  23. 23. Implementation – templates (5/6)  Embed your latest video by change the video id, {{id}}, to the embedded code provide by Youtube. 1. <object width="425" height="344"> 2. <param name="movie" value="http://www.youtube.com/v/{{ id }}&hl=z h_TW&fs=1&"></param> 3. <param name="allowFullScreen" value="true"></param> 4. <param name="allowscriptaccess" value="always"></param> 5. <embed src="http://www.youtube.com/v/{{ id }}&hl=zh_TW&fs=1&" typ e="application/x-shockwave- flash" allowscriptaccess="always" allowfullscreen="true" width="4 25" height="344"></embed> 6. </object> WECO Lab, CSIE dept., FJU March 2, 2010 23 http://www.weco.net
  24. 24. Implementation – templates (6/6)  Where the result of main.html diplay. 1. {% block content %} 2. {% endblock %}  We can also add some widgets here. Like Google Calendar or Google Map 1. <h2>My Schedule</h2> 2. <iframe src="http://www.google.com/calendar/embed?showTitle=0&sho wNav=0&showDate=0&showPrint=0&showTabs=0&showCalendars=0&mode=AGE NDA&height=400&wkst=1&bgcolor=%23453&src=weco.net_fm86efcblmn4qle bh9kometb6o%40group.calendar.google.com&color=%232952A3&ctz=Asia% 2FTaipei" style=" border- width:0 " width="290" height="400" frameborder="0" scrolling="no" ></iframe> WECO Lab, CSIE dept., FJU March 2, 2010 24 http://www.weco.net
  25. 25. demo WECO Lab, CSIE dept., FJU March 2, 2010 25 http://www.weco.net
  26. 26. Q&A Thanks for listening! WECO Lab, CSIE dept., FJU March 2, 2010 26 http://www.weco.net

×