how to build a personal portal on google app engine with django
DESCRIPTION
Speaker: Jimmy Lu Topics: How To Build A Personal Portal On Google App Engine With Django Date: 2010.02.19 WECO Lab, CSIE, FJUTRANSCRIPT
WECO Seminar Part II
How to build a personal portal on Google App Engine with Django
Speaker : Jimmy LuAdvisor : Hsing Mei
Web Computing LaboratoryComputer Science and Information Engineering
DepartmentFu Jen Catholic University
………
April 10, 2023 2WECO Lab, CSIE dept., FJU http://www.weco.net
Outline
• Design your personal portal• Environment settings
main.py settings.py app.yaml
• Implementation• Demo• Q&A
April 10, 2023 3WECO Lab, CSIE dept., FJU http://www.weco.net
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 Google Map
April 10, 2023 4WECO Lab, CSIE dept., FJU http://www.weco.net
Environment settings(1/5)
main.py1. import os 2. # point to seetings.py, then django knows how to configure
the environment 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 libr
ary 9. use_library('django', '1.1')
April 10, 2023 5WECO Lab, CSIE dept., FJU http://www.weco.net
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()
April 10, 2023 6WECO Lab, CSIE dept., FJU http://www.weco.net
Environment settings(3/5)
settings.pyimport 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 = '‘
# localizationTIME_ZONE = 'Asia/Taipei’LANGUAGE_CODE = 'zh-TW '
April 10, 2023 7WECO Lab, CSIE dept., FJU http://www.weco.net
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.
April 10, 2023 8WECO Lab, CSIE dept., FJU http://www.weco.net
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
April 10, 2023 9WECO Lab, CSIE dept., FJU http://www.weco.net
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: 11. model = BlogPost
April 10, 2023 10WECO Lab, CSIE dept., FJU http://www.weco.net
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)
April 10, 2023 11WECO Lab, CSIE dept., FJU http://www.weco.net
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 d
isplay 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():
April 10, 2023 12WECO Lab, CSIE dept., FJU http://www.weco.net
Implementation – views(2/8)
8. # Save the BlogPost object without save it to the database(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))
April 10, 2023 13WECO Lab, CSIE dept., FJU http://www.weco.net
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 Goog
le 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. 10. return render_to_response('upload.html')
April 10, 2023 14WECO Lab, CSIE dept., FJU http://www.weco.net
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 G
oogle images api stores modified images as by default 7. response['Content-Type'] = 'image/png' 8. 9. return response
April 10, 2023 15WECO Lab, CSIE dept., FJU http://www.weco.net
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 ge
tting your uploaded video. 3. url = "http://gdata.youtube.com/feeds/api/users/
gn00023040/uploads" 4. # Fetch the result from url by urlfetch API provided by
Google App engine. 5. result = urlfetch.fetch(url) 6. id = ''
April 10, 2023 16WECO Lab, CSIE dept., FJU http://www.weco.net
Implementation – views(6/8)
7. if result.status_code == 200: 8. # Parse the XML format by minidom which is a python b
uild-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].dat
a[42:] 16. 17. return id
April 10, 2023 17WECO Lab, CSIE dept., FJU http://www.weco.net
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)
April 10, 2023 18WECO Lab, CSIE dept., FJU http://www.weco.net
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 templat
e will process the result. 14. return HttpResponse(t.render(c))
April 10, 2023 19WECO Lab, CSIE dept., FJU http://www.weco.net
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>
April 10, 2023 20WECO Lab, CSIE dept., FJU http://www.weco.net
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/from-data or request.FILES will receive nothing. -->
2. <form action="{%url views.upload%}" method="post" enctype="multipart/form-data">
3. <input type="file" name="img" /> 4. <input type="submit" value="Upload" /> 5. </form>
April 10, 2023 21WECO Lab, CSIE dept., FJU http://www.weco.net
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 %}
April 10, 2023 22WECO Lab, CSIE dept., FJU http://www.weco.net
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 function 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 %}
April 10, 2023 23WECO Lab, CSIE dept., FJU http://www.weco.net
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=zh_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&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed>
6. </object>
April 10, 2023 24WECO Lab, CSIE dept., FJU http://www.weco.net
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&showNav=0&showDate=0&showPrint=0&showTabs=0&showCalendars=0&mode=AGENDA&height=400&wkst=1&bgcolor=%23453&src=weco.net_fm86efcblmn4qlebh9kometb6o%40group.calendar.google.com&color=%232952A3&ctz=Asia%2FTaipei" style=" border-width:0 " width="290" height="400" frameborder="0" scrolling="no"></iframe>
April 10, 2023 25WECO Lab, CSIE dept., FJU http://www.weco.net
demo
April 10, 2023 26WECO Lab, CSIE dept., FJU http://www.weco.net
Q&A
Thanks for listening!