使用Python Django-nonrel开发GAE应用之使用taskqueue处理缓存,提高性能

task queue

顾名思义,就是任务队列,Google App Engine的中文文档里面没有这一项,(可能是因为目前还处于labs里面的Experimental状态,不会重点介绍)但是我觉得还是有用。大家不妨看看英文文档: http://code.google.com/intl/en/appengine/docs/python/taskqueue/

 

使用场合

刚刚说到有用,我用在什么地方呢?就是处理缓存。

我们上篇说到我们处理缓存通过cron来定期处理,但是我们知道cron是要写清楚每条地址的,如果我们想把数据的1000个分页都缓存好,一次缓存完是不行的,因为30秒的限制,只能分开缓存,是不是要在cron里面写1000条?那太蠢了。我们就用task queue来做。

 

使用方法

  • 配置taskqueue

  • 添加taskqueue的代码

  • from google.appengine.api.labs import taskqueue
    
    taskqueue.add(url='/path/to/my/worker')
    taskqueue.add(url='/path?a=b&c=d', method='GET')

管理 taskqueue地址

管理地址在: /_ah/admin/queues ,比如:http://localhost:8000/_ah/admin/queues

 

应用举例

#viewaddtask.py
def add_task(request,task=None,*qp):
    
    if (task):
        task = task.strip()
        if (task=='taskqueue'):            
            ...            
            result_all = ''
            for category in catelist:
               for infotype in typelist:
                   for location in locationlist:
                       for date_one in datelist:
                           # Add the task to the default queue.
                           myurl = '/proj/task/cache_page_non_force/%s-%s-%s-%s-%s-%s-%s/'%(category,infotype,location,date_one['year'],date_one['month'],date_one['day'],'1')
                           taskqueue.add(url=myurl,method='GET')
                                                       
                           result_all = result_all +'<br/>'+ myurl
                       
            return HttpResponse(result_all)

BUG?错误?

我曾经使用 taskqueue.add(url=myurl) ,发现返回403错误,

然后我改为使用taskqueue.add(url=myurl,method='GET'),才能成功。

自己动手,苹果 Nano 3 换电池记

前因

一位朋友的Nano3代小胖子,买了没用几次,最近拿出来,发现开不了机了。

找人咨询,因为过了保修期,说修要价格的70%,买的时候可是千多元啊!

遂找我,看我有没有什么办法。

分析故障

开机没反应,主板问题?电池问题?

看情形,由于长期搁置,电池损坏的可能性很大。

确认确认

为了确认是电池问题,我拿了条连接线,连上电脑,有时候竟然可以正常播放,甚至显示正在充电,只是拔掉线之后,还是毫无反应。但是这基本让我确认是电池故障。

如何更换,

怎么换电池啊?

研究中

去网上找资料,看拆机过程的记录,

找谁换?

自己换吗?

谷歌一下,发现还比较麻烦:

第一,电池是焊接在主板上的,要拆掉原来的3条线,重新焊接上去

第二,开盖不好开,

找别人换?

找Apple的售后,深圳倒是有两家,但是估计用修理费可以买个其他牌子的新Mp3了。

去网上找维修的,很多针对IPhone,修这个还真不多。

淘宝网上买电池的倒是不少,电池也不贵,20大洋,但是一一咨询,都不愿帮你换电池,只卖电池

有一家指导我说买个电池,找维修手机的焊接一下…

多次寻找,找到一家,愿意换,而且价格不贵说只要60,我想,收40块开机、手工费也不算多遂约定上门前往

令人鄙视的态度

找到维修店子,店小二在,老板不在,老板来才能报价、维修(老板是技术出身),攀谈中… 发现是老乡,本以为这事能成,半小时后,老板来了,神奇冷漠,开价120,拒不还价,我说在网上联络过,报价60的,他电话和他们负责网上服务的人联系后,竟然后者脸皮说我说错了,不知道是Nano3,可我说网上聊天可是清清楚楚的。我知道多说这些没有用处,还价,被拒,走人。不是钱的问题,主要是鄙视老板的态度和人品。

自己动手?

决定自己动手,好歹也是理工科出身的,上学时候还焊过一台收音机呢,另外再找个经常焊过东西的帮手。

购买配件:电池,后盖,开机工具,总共花费67大洋,包括运费(和额外一条数据线)

动手

到货后,动手,开盖,果然,不好开,从数据接口入手,只能用蛮力,边缘有点弄花,唉

果然是三条线,是不是把线剪断,直接把线接起来算了,就不动主板其他部分??

等帮手,拿电烙铁来…

帮手,波折

继续拆机,还是觉得直接焊到主板上,遂拆掉螺丝,断开排线,一条接屏幕一条接转盘的,

清除原来的,接上新的电池,

通电,开机,咦,怎么屏幕没东西,按键,塔塔,有按键声音,屏幕排线没接好?

重新接排线,哦,好了,

接外壳,完工。

总结

没有经验,所以弄花了外壳的边缘。

使用Python Django-nonrel开发GAE应用之GAE限制和性能优化

update:2010-08-30

Google 发布GAE SDK 1.3.6 ,对1000条限制有修改,QuerySet.all().count()返回实际数目而不是最多1000,切片也允许下标大过1000了,所以分页问题完美解决了。

 

GAE限制

GAE查询限制

Django的查询本来是非常强大的,可惜GAE不能完全支持,很多高级的搜索不支持也就算了,但是多个条件的非相等查询都不支持还是非常令人沮丧的。

具体的限制可以参考这里:http://www.allbuttonspressed.com/projects/djangoappengine(需翻墙)

为了规避这些限制,只能冗余一些字段来规避非相等的查询,比如日期查询和多级地区查询。好在Django的Model很好用,通过save(),可以方便冗余字段。

GAE 1000条限制

QuerySet.filter(…).count()的最大返回值是1000,

切片QuerySet.all()[1000:1005]是非法的查询

Count总是还是有办法计算的,比如通过

record_count = len(QuerySet.all().values(‘id’))

但是实际运行速度是很慢的,所以谨慎使用。

至于切片,好像没办法,查询集大于1000条,想通过切片来分页是不行的。

不过QuerySet.all()本身是可以返回多余1000条的,如果把这个结果缓存起来,自己进行切片,我不知道效果会怎么样,但是又要小心1M的限制。

GAE 30秒限制

一个页面不能响应时间不能超过30秒,我原来以为应该限制不大,不过我第一次把应用上传上去才发现,首页就打不开,因为超过30秒了。Google把它叫做DeadlineExceededError,我打开GAE的log,全部都是这个错误。

没办法,只好去进行优化

 

性能优化

cache

Django的cache系统还是不错的,系统介绍请参考:http://docs.djangoproject.com/en/1.2/topics/cache/

谈谈我用到的,

per-view的Cache,

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)
def my_view(request):

View级别的缓存算是级别比较高了,如果页面不能出来,第一次都运行不了,View缓存是无法生成的,所以还需低级别的缓存

Template 缓存

{% load cache %}
{% cache 500 sidebar %}
    .. sidebar ..
{% endcache %}

更低级别的缓存就变量级别的

class utils():
    
    @staticmethod
    def cache_get(key):
        return google.appengine.api.memcache.get(key)

    @staticmethod
    def cache_put(key, value, duration):
        if (google.appengine.api.memcache.get(key)):
            google.appengine.api.memcache.set(key, value, duration)
        else:    
            google.appengine.api.memcache.add(key, value, duration)


调用示例

def get_bidcategory_list(force_update=False): 
    if force_update==False:
        bidcategory_list =  myutils.cache_get('bidcategory_list')
        if bidcategory_list:
            return  bidcategory_list  
        
    bidcategory_list = BidCategory.objects.all().order_by('categorycode')
    myutils.cache_put('bidcategory_list',bidcategory_list,60*60)
    return bidcategory_list


首先建立低层次的缓存,上一级别的页面就能出来,View级别的缓存就建立了,有无View缓存时访问速度完全不可同日而语啊。

但是怎么建立定时刷新这些缓存呢,所以cron就来了。

cron

请参考google的cron介绍http://code.google.com/intl/zh-CN/appengine/docs/python/config/cron.html

我只举个例子

#cron.py

cron:
- description: keep alive
  url: /
  schedule: every 20 minutes
- description: cachetabs
  url: /proj/task/cachetabs/
  schedule: every 2 hours
- description: cachedays
  url: /proj/task/days/
  schedule: every 10 hours
- description: cachemonths
  url: /proj/task/months/

如此这边我的页面总算能出来了,想要体验良好,还需慢慢调优,呵呵

使用Python Django-nonrel开发GAE应用之实现数据导出和导入

背景:

总有些数据需要在开发版本和发布版本之间同步,所以能实现数据的导入导出是需要的。

构想:

通过Django管理界面导出Model的XML序列化数据,然后,开发一个导入XML序列化数据的界面。

实现:

基于Django管理界面的导出功能

from django.http import HttpResponse
from django.core import serializers

#导出XML
def export_as_xml(modeladmin, request, queryset):
    response = HttpResponse(mimetype="text/xml")
    serializers.serialize("xml", queryset, stream=response)
    return response

#注册
admin.site.add_action(export_as_xml)

效果

django_admin_export_xml

基于序列化的导入功能

模板importxml.html

<html><head><title>import</title></head>
<body>

<h1>import xml</h1>
<form  action="" method="post">
{% csrf_token %}
<textarea name="xmldata" rows="20" style="width:600px;" ></textarea>
<br/>
<input type="submit" value="import">{{ msg }}

</form>

</body></html>


views中的导入代码

from django.http import HttpResponse
from django.core import serializers

def importxml(request):
    data = request.POST.get('xmldata')
    msg = []
    if data:
	data = data.encode('utf-8')
        for deserialized_object in serializers.deserialize("xml", data):
            #if object_should_be_saved(deserialized_object):
                deserialized_object.save()
        msg = 'saved'
    else:
        msg = ''
    return render_to_response('importxml.html', 
                                       {'value_list': '','action':'','msg':msg})


在urls.py中添加映射,即告成功。

测试验证

1.选择一个数据量不多的表,全选,然后导出xml保存。

2.删除表的全部数据

3.将保存的xml拷贝到import界面的文本框,点击导入

4.去检查一下,是不是删除的数据又回来了。

关于Django1.2的错误CSRF verification failed. Request aborted.

错误:

CSRF verification failed. Request aborted.

原因:

Cross Site Request Forgery protection¶

参考:

http://docs.djangoproject.com/en/dev/ref/contrib/csrf/

解决步骤:

1.修改setting.py文件中的MIDDLEWARE_CLASSES

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.middleware.csrf.CsrfResponseMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)

2.添加csrf_token

<form  action="" method="post">
{% csrf_token %}

使用Python Django-nonrel开发GAE应用之Django model及管理界面小技巧

models定义小技巧

Django-nonrel的ORM使用很方便,只需要定义Model就可以了,下面是些常用的技巧

class BidCategory(models.Model):
    #主键,自动生成的ID
    id = models.AutoField('id', primary_key=True)
    title = models.CharField('标题',max_length=50)
    #自动生成的当前日期
    create_date = models.DateField('创建时间',auto_now=True)
    description = models.CharField(max_length=500, blank=True,
        help_text='This is description')
    #自关联的定义
    parentcategory = models.ForeignKey('self', 'id', null=True,blank=True,
        #default=default_BidLocation,
        help_text="上级")
    
    #管理界面中显示外键选择时候的标题
    def __unicode__(self):
        return self.title

 

自定义管理界面

如果不需要特别定制管理界面,只需要admin.site.register(BidCategory)就可以在管理界面中看到我们定义的Model,为了管理界面看起来友好,还是需要做些自定义的。

class BidCategoryAdmin(admin.ModelAdmin):
    #管理界面列出的列
    list_display = ('id', 'title')
    #管理界面都所的列
    search_fields = ('title',)
    #排序列
    ordering = ('title',)

#自定义管理界面
admin.site.register(BidCategory,BidCategoryAdmin)

GAE管理帐号

 

python manage.py createsuperuser创建的用户是本地的用户,项目Deploy到GAE后,用户信息和数据并不会传到GAE。

创建GAE管理帐号,远程命令:

python manage.py remote  createsuperuser


另:中文问题

我使用Eclipse开发,

将window>>preferences>General>workspace>Text file encoding >other(Utf-8)

在.py文件顶部加入说明 # -*- coding: utf-8 -*-

Django-nonrel 入门之添加Django Book到testapp

上篇已经建立好testapp,本篇介绍如何将

http://www.djangobook.com/en/2.0/chapter01/介绍的内容: Django Book 示例加入到我们刚刚建立的testapp中来。

 

步骤如下:

1.定位到testapp的src目录,执行命令: python manage.py  startapp book

这会建立一个book模块和book文件夹,并有下列文件

      1. __init__.py
      2. models.py
      3. tests.py
      4. views.py
  1. 2.到http://www.djangobook.com/en/2.0/chapter01/页面,拷贝相应的代码到book目录下相应的文件。
  2. # models.py ,views.py ,urls.py 已经建好,更新内容即可。
  3. # latest_books.html 需要新建目录 templates,并新建文件 latest_books.html。

 

3.修改 settings.py的INSTALLED_APPS,添加'book'

INSTALLED_APPS = (
                   'django.contrib.admin',
    'django.contrib.auth',
    'djangotoolbox',
#    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'book',
)

4.修改urls文件,添加 (r'^book/', include('book.urls')),
urlpatterns = patterns('',
   (r'^admin/', include('urlsadmin')),
    (r'^book/', include('book.urls')),
    ('^$', 'django.views.generic.simple.direct_to_template',
     {'template': 'home.html'}),
)

 

5.步骤完成,run,输入地址http://localhost:8000/book/latest/ 可看到如下界面为成功。(因为book数据库中没有数据,所以下面显示为空)

image

6.如果只需要在管理界面修改的内容,我们可以直接使用Django的管理界面来增删改。(参考:http://www.djangobook.com/en/2.0/chapter06/

首先我们需要修改配置以访问管理界面

要点1:(setting.py文件中,INSTALLED_APPS中'django.contrib.admin' ,'django.contrib.auth', 'django.contrib.contenttypes' and 'django.contrib.sessions'

INSTALLED_APPS = (
   'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.sessions',
    'django.contrib.contenttypes',
    #'django.contrib.sites',
    'django.contrib.sitemaps',
    'djangotoolbox',
#    'django.contrib.auth',
    'book',
)

要点2:修改urls.py,patterns中添加

(r'^admin/', include(admin.site.urls)),

要点3:添加book/admin.py文件

内容如下

from django.contrib import admin

from mysite.books.models import  Book 

admin.site.register(Book)

修改完成。

效果如图:

image

添加几个再回到http://localhost:8000/book/latest/

image

Django-nonrel 入门之 django-testapp

本文介绍如何运行Django-nonrel的实例程序django-testapp。

下载下列 zip 文件

解压所有的文件.

django-testapp 文件夹里面包含的文件是简单的实例项目所需要的文件.如果你想要开始一个新的项目,可以拷贝manage.py, settings.py, and app.yaml 文件到你的项目,按需要修改 settings.py 和app.yaml 即可.

 

拷贝文件夹到你的项目 (比如, django-testapp):

  • django-nonrel/django
  • djangotoolbox/djangotoolbox
  • djangoappengine

最后形成的文件夹结构应该是这样的:

* django-testapp
     * django
     * djangotoolbox
     * djangoappengine
     * ...

 

通过 python manage.py runserver 运行

访问http://localhost:8000/显示如下,即表示大功告成。

image

上传到GAE,demo如下:

http://django-nonrel.appspot.com/

配置Eclipse使用Django-nonrel框架开发GAE应用入门

为什么?

为什么选择GAE?

GAE即Google App Engine。是Google免费提供的一个平台,空间够大,也可以用数据库(特殊的),一般的网站和应用完全没问题,不过不去使用,确实是暴殄天物。(不过我们伟大的墙把GHS给屏蔽光了,用起来困难一些)

为什么选择django?

GAE现在支持Java和Python,Python是GAE最先支持的语言(应该支持的比较好吧),开发应用不过任何框架,应该这年头没有人会这样搞了吧,而Python下最成熟的框架就是django了。django提供

为什么选择Django-nonrel

在GAE下使用django会有个限制,django的ORM并不支持GAE的bigtable数据库,Django-nonrel就顺势而出(还支持其他的非关系型数据库)。

http://www.allbuttonspressed.com/projects/django-nonrel (需翻墙)

 

如何设置

  1. 1.配置 Windows 版 Eclipse 以便与 Google App Engine 配合使用
  2. 2.参考http://www.allbuttonspressed.com/projects/django-nonrel , 下载 allbuttonspressed.zip (需翻墙) 
  3. 3.在Eclipse中设置Run选项

Main Tab:

Main Module

${workspace_loc:allbuttonspressed/src/manage.py}

Argument Tab:

Program arguments

runserver

Working directory 设置为other

${workspace_loc:allbuttonspressed/src}  (即app.yaml.所在目录)

使用

python manage.py syncdb 数据库

python manage.py createsuperuser 创建超管用户

python manage.py runserver 运行

其他参考:

http://www.allbuttonspressed.com/blog/django/2010/02/4-things-to-know-for-NoSQL-Django-coders

http://www.allbuttonspressed.com/projects/djangoappengine

运行效果

image

如果出现这样的问题:

Q:Could not initialize images API; you are likely missing the Python
"PIL" module. ImportError: No module named PIL

A:You have to install the PIL module before using the new SDK.
Instructions for various platforms are located here:
http://code.google.com/appengine/docs/images/installingPIL.html

SharePoint Server Enterprise 2010 中文版初体验[图解]

1.安装界面

sharepoint2010

2.配置界面,和2007版几乎没有差异

sharepoint2010config

3.管理中心界面,首页列出的是各个子项中比较常用的设置,如果点击左边列表中的子项,有更多的设置项。

sharepoint2010admin

4.新网站,选择模板的界面。可以看到多了一些模板。

sharepoint2010templates

5.为网站设置用户组

sharepoint2010auth

6.我使用商业智能中心模板建立出来的网站

sharepoint2010BIcenter

走马观花,先这样吧。