Archive for the ‘App Engine’ Category

Get Total count from datastore in app engine

Posted on November 3rd, 2008 in App Engine, Google, Programming | No Comments »

Before you continue to read the post, i have to warn you that this is not the best way of getting the total count and there would be a possible inaccuracy and may not be scalable (http://groups.google.com/group/google-appengine/browse_thread/thread/3abb2868ab5fc304?pli=1), please use shared counter as what david suggested.

Here is a way on how to get the total count from a datastore in app engine, this uses memcache to cache the count for one minute (you can change this by passing an argument), i’m not sure but this seems to be better coz it doesn’t need you to do some writing on datastore.

from google.appengine.api import memcache
def get_total_count(self,model,cacheTime = 60,maxNumber = 10):
cacheName = model.kind() + “_totalCount”
total = memcache.get(cacheName)
if total == None:
index = 0
currentTotal = total = len(model.all().fetch(maxNumber,0 ))
while currentTotal == maxNumber:
index += 1
currentTotal = len(model.all().fetch(maxNumber,maxNumber * index))
total += currentTotal
memcache.add(cacheName, total, cacheTime)
return total

To call it on your get function:
self.response.out.write(str(get_total_count(self,<your model>))
or
self.response.out.write(str(get_total_count(self,<your model>,3600,1000))

* Remember that the maxNumber argument can only support upto 1000 and i encourage you to set it to 1000 if your datastore is big

Explanation to the codes:
cacheName = model.kind() + “_totalCount”
Create a variable and name it as our model’s name with an underscore totalCount (you can change this one)

total = memcache.get(cacheName)
if total == None:
index = 0

Change if there is already a cached value, if not set a index variable to 0 and ….

currentTotal = total = len(model.all().fetch(maxNumber,0 ))
Set the currentTotal and total variable to the len of a fetched row limit by maxNumber starting with the row 0

while currentTotal == maxNumber:
index += 1
currentTotal = len(model.all().fetch(maxNumber,maxNumber * index))
total += currentTotal

Loop until the currentTotal is not equal to the maxNumber and add the currentTotal to the total variable and add one to the index. Why do a while loop on currentTotal == maxNumber? Since we set a upper limit on the maximum number of rows we could fetch, it logically means that if we loop with the upper limit it would come to a point where it would never be equal to that limit.

memcache.add(cacheName, total, cacheTime)
Cache our total

Hope i’m right and it helps :)

CamelCase in Python / Django

Posted on October 30th, 2008 in App Engine, Programming | No Comments »

Here is a small script for making CamelCase string in python

import re
from string import capitalize
def camelcase(value):
return "".join([capitalize(w) for w in re.split(re.compile("[\W_]*”), value)])

in django just add
@register.filter

making it
import re
from string import capitalize
@register.filter
def camelcase(value):
return "".join([capitalize(w) for w in re.split(re.compile("[\W_]*”), value)])

Hope it help.

Auto Increment in App Engine

Posted on October 23rd, 2008 in App Engine, Google | No Comments »

So you want to implement auto increment on your datastore? Here is a simple tutorial of how to do it on App Engine. This auto increment will use integers, this does not cover more advance auto increments one like UUID.

For our example we would use this datastore model:
class Post(db.Model):
title = db.StringProperty()
body = db.StringProperty()

Then you would save records like with something like
post = Post()
post.title = "Example"
post.body = "This is the body"
post.put()

Then you shall see this saved on the datastore. But where did i declared the id? App engine by default will give each record a Key, having said that each row by default will have an auto incremented integer. To retrive a row by the id you would do something like
currentPost = Post.get_by_id(<id of the post>)

What if i fetch from the model, how can i get the id?
query = datamodel.Post().all()
for result in query:
self.response.out.write(result.key().id())

How can i get my auto generated id on templates?
{% for post in posts %}
{{ post.key.id }}
{% endfor %}

Use HTML on App Engine

Posted on October 22nd, 2008 in App Engine, Google | No Comments »

App Engine by default uses django, a Python web framework that’s a bit like Rails or CakePHP, most of the tutorial on the App Engine Documentation would not teach you to use Templates except the main Using Templates part. While this tutorial is good, it would not teach you how have a more optimized version. Here is how i did, i suggest you to read the App Engine Using Templates Tutorial:

import os
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
def page_display(page,file,values={}):
template_values = {}
template_values.update(values)
try:
template_values.update(page.template_values)
except:
pass
path = os.path.join(os.path.dirname(__file__),file)
page.response.out.write(template.render(path,template_values))
class MainPage(webapp.RequestHandler):
def get(self,page):
self.template_values = {
"message" : "Hello World",
"message2" : "Hello"
}
page_display(self,"templates/index.html")
def main():
application = webapp.WSGIApplication(
[
('/', MainPage)
],
debug = True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == “__main__”:
main()

As you can see if you have a lot of classes it would be a easier to remember and use
page_display(self,"templates/index.html")
then
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))

Alternate row colors in App Engine

Posted on October 20th, 2008 in App Engine, Google, Programming | No Comments »

You have a senario where you need to have alternating colors in each rows of data in app engine or django, how can you achieve this? Here is a simple solution on doing it (This took me more than 30 mins to find out the solution coz most of the time they will give you php’s solution on alternating rows)
{% for video in videos %}
<div class="row {% cycle odd,even %}">
{{ video.title }}
<div class="youtubeLink">
<a href="{{ video.youtube_id }}">
{{ video.youtube_id }}
</a>
</div>
</div>
{% endfor %}

The main solution is this code
{% cycle odd,even %}

What this do is that it cycles around each row and returns the right index (odd or even). And with this function you are not bound to just 2 selections, if you want more you could just do something like
{% cycle one,two,three,four %}

Hope this helps.

Getting Server Information in Templatetags

Posted on October 18th, 2008 in App Engine, Google | No Comments »

In app engine you might want to get the server information like the hostname, current url and so on, currently you can do this by passing the self.request to the template values, and from template to your filter. What if you don’t want to pass the request variable everytime? Here is a how i did it (i’m not a python guy so if i did something wrong do comment thanks) (Here is the Tutorial on templatetags)

In your templatetags:def get_server_information(all,info = 1):
if info == 1:
return wsgiref.handlers.BaseHandler().os_environ
else:
return wsgiref.handlers.BaseHandler().os_environ.get(info)

Now in your templates if you want to get the whole server information
{{ 1|get_server_information }}

would print something like:
{'HTTP_COOKIE': 'SESSION_ID=randomstring; dev_appserver_login="test@example.com:False"',
'SERVER_SOFTWARE': 'Development/1.0',
'SCRIPT_NAME': '',
'REQUEST_METHOD': 'GET',
'HTTP_KEEP_ALIVE': '300',
'SERVER_PROTOCOL': 'HTTP/1.0',
'QUERY_STRING': '',
'CONTENT_LENGTH': '',
'HTTP_ACCEPT_CHARSET': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'HTTP_USER_AGENT': 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 Ubuntu/8.04 (hardy) Firefox/3.0.3 FirePHP/0.1.2',
'HTTP_CONNECTION': 'keep-alive',
'SERVER_NAME': 'localhost',
'REMOTE_ADDR': '127.0.0.1',
'PATH_TRANSLATED': '/path/to/your/current/python/code',
'SERVER_PORT': '8080',
'CONTENT_TYPE': 'application/x-www-form-urlencoded',
'CURRENT_VERSION_ID': '1.1',
'HTTP_HOST': 'localhost:8080',
'TZ': 'UTC',
'USER_EMAIL': 'test@example.com',
'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'APPLICATION_ID': 'yourapplicationid',
'GATEWAY_INTERFACE': 'CGI/1.1',
'HTTP_ACCEPT_LANGUAGE': 'en-us,en;q=0.5',
'AUTH_DOMAIN': 'gmail.com',
'HTTP_ACCEPT_ENCODING': 'gzip,deflate',
'PATH_INFO': '/examples/home'}

So you have guessed if you want only the path info then you do
{{ 1|get_server_information:”PATH_INFO” }}

Hope this helps :)