nginx 配置

2009年3月27日 roboter 没有评论

如果需要配置反向代理,则nginx编译的时候需要有–with-http_realip_module参数,于是重新配置编译了一下,这次把大部分参数都加上了

./configure –conf-path=/etc/nginx/nginx.conf –error-log-path=/var/log/nginx/error.log –pid-path=/var/run/nginx.pid –lock-path=/var/lock/nginx.lock –http-log-path=/var/log/nginx/access.log –http-client-body-temp-path=/var/lib/nginx/body –http-proxy-temp-path=/var/lib/nginx/proxy –http-fastcgi-temp-path=/var/lib/nginx/fastcgi –prefix=/usr –with-http_stub_status_module –with-http_realip_module –with-http_dav_module –with-http_flv_module –with-http_sub_module –with-http_addition_module

反向代理配置参数如下:

upstream hosts_xxx_com {
server www.destsite.com:80;
}
server {
listen       80;
server_name  www.xxx.com;

access_log  /var/log/nginx/xxx.host.access.log;

location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_pass http://hosts_xxx_com; #这个可以取任意名字,和upstream的名字相同即可
proxy_set_header  x-real-IP  $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

有时候需要需要保护一些目录,限制某些ip访问,可以如下设置:

location ^~ / {
allow   127.0.0.1;
allow   192.168.1.2;#服务器ip
deny    all;
}

如果需要禁止整个域名的访问,可以设置在server中:

allow   192.168.1.2;#自已电脑的ip
deny    all;

可以把限制ip单独弄出一个文件deny.conf,在nginx.conf中include deny.conf;。如果需要动态添加一些限制ip,则可以修改这个deny.conf文件,修改完成之后,通过信号告诉nginx,限制就生效了。

防盗链设置:使用别名配置

location /res/ {
alias   /opt/Src/;
valid_referers none blocked server_names *.xxx.com ;
if ($invalid_referer) {
return 403;
}
}

nginx的信号如下:转摘自常用的 Nginx 参数和控制

通过信号对 Nginx 进行控制
Nginx 支持下表中的信号:
信号名         作用描述
TERM, INT         快速关闭程序,中止当前正在处理的请求
QUIT         处理完当前请求后,关闭程序
HUP         重新加载配置,并开启新的工作进程,关闭就的进程,此操作不会中断请求
USR1         重新打开日志文件,用于切换日志,例如每天生成一个新的日志文件
USR2         平滑升级可执行程序
WINCH         从容关闭工作进程

有两种方式来通过这些信号去控制 Nginx,第一是通过 logs 目录下的 nginx.pid 查看当前运行的 Nginx 的进程 ID,通过 kill – XXX <pid> 来控制 Nginx,其中 XXX 就是上表中列出的信号名。如果您的系统中只有一个 Nginx 进程,那您也可以通过 killall 命令来完成,例如运行 killall – s HUP nginx 来让 Nginx 重新加载配置。

分类: linux 标签:

ubuntu nginx django安装记录

2009年3月26日 roboter 1 条评论

需要安装一台服务器,主要作为图片的处理存储显示等功能,选择了ubuntu作为服务器,ubuntu的服务器版本只有500多M,非常小巧,同时使用人数众多,有什么问题能够很好解决。

使用的是2M带宽,ubuntu 8.04只用40多分钟就全部下下来了。安装很快完成,进入了配置。

首先尝试安装django,直接使用sudo apt-get install python-django,结果把0.96.1的版本给弄下来了,只能删除这个包了,sudo apt-get remove python-django,直接wget http://www.djangoproject.com/download/1.0.2/tarball/,下了一个1.0.2版本,顺利安装,然后又安装了PIL图形处理库,这次直接用sudo apt-get install python-imaging,PIL的最后一个版本在06年底发布,两年多了,没有再发布新版本,但还是有很多地方在用。

nginx很牛,所以想试试。nginx 8.04已经有了一个0.5版本,太老了,从nginx网站下了一个当前最新的0.7.44版本,开始configure,报没有pcre,zlib等模块。打算使用zlib,pcre等的最新版本,就使用wget下了最新的模块,config没有问题,却报没有make,ubuntu 8.04.2服务版本连make都没有,真是够简洁的。没有make,也没有gcc,g++等工具了,不过都可以用apt下载安装,还是方便。

nginx0.5 已经在服务器中配置好了,包括在/etc/init.d中的脚本,所以就打算覆盖安装,可以省一些事情。nginx 0.5的配置参数为

–conf-path=/etc/nginx/nginx.conf –error-log-path=/var/log/nginx/error.log –pid-path=/var/run/nginx.pid –lock-path=/var/lock/nginx.lock –http-log-path=/var/log/nginx/access.log –http-client-body-temp-path=/var/lib/nginx/body –http-proxy-temp-path=/var/lib/nginx/proxy –http-fastcgi-temp-path=/var/lib/nginx/fastcgi –with-debug –with-http_stub_status_module –with-http_flv_module –with-http_ssl_module –with-http_dav_module。

将相关的路径参数拷贝下来,再加上设定–prefix=/usr。其他的参数不要,这样就顺利安装了。执行/etc/init.d/nginx start ,看到了欢迎页面。

还需要安装flup,django站点中的flup链接报错,google了一下,找到1.0.1的下载地址http://www.saddi.com/software/flup/dist/flup-1.0.1.tar.gz,直接下载安装。

拷贝django提供的脚本,进行部分修改,可以方便启动django:

#!/bin/bash

# Replace these three settings.
PROJDIR="/home/user/myproject"
PIDFILE="$PROJDIR/mysite.pid"
SOCKET="$PROJDIR/mysite.sock"

cd $PROJDIR
if [ -f $PIDFILE ]; then
    kill `cat -- $PIDFILE`
    rm -f -- $PIDFILE
fi
exec python manage.py runfcgi pidfile=$PIDFILE host=127.0.0.1 port=8080

可以将这个脚本放入/etc/init.d/目录下,再在rcx.d目录加上一个链接,就可以实现开机自动启动django。

在/etc/nginx/nginx.conf文件中,主要server中配置,加上如下语句:

server {
listen 80;
server_name localhost;
access_log    /var/log/nginx/localhost.access.log;
location / {
# host and port to fastcgi server
fastcgi_pass 127.0.0.1:8080;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_pass_header Authorization;
fastcgi_param REMOTE_ADDR           $remote_addr;
fastcgi_param SERVER_PROTOCOL       $server_protocol;
fastcgi_param SERVER_PORT           $server_port;
fastcgi_param SERVER_NAME           $server_name;
fastcgi_intercept_errors off;
}
location ^~ /media/ {
alias  /usr/lib/python2.5/site-packages/django/contrib/admin/media/;
}
location ~* ^.+\.(gif|png|jpg|jpeg|css|swf|htm|html|asp|php|jsp|js|doc|txt)$ {
root   /usr/lib/python2.5/site-packages/django/contrib/admin/media/;
access_log   off;
}
}

现在可以看到页面了,但是,还有问题!

使用了mysql作为django的后台数据库,mysql是ubuntu帮忙安装好的,结果python manage.py syncdb的时候报错:

_mysql_exceptions.Warning: Incorrect string value: ‘\xE4\xB8\x8A\xE4\xBC\xA0…’ for column ‘name’ at row 1

估计是字符编码的问题,难道mysql缺省不是utf8吗?查了一下,默认的是Latin1编码,在/etc/my.cnf中,[client]和[mysqld]下面均加上default-character-set=utf8,这样变成了utf8的编码,这个问题解决了。

然后可以看到首页内容了,以为应该差不多了。然后依然还有问题:进入admin界面,报错:

Unhandled Exception

An unhandled exception was thrown by the application.

检查了error.log,如下:

2009/03/25 23:26:05 [error] 17966#0: *6 FastCGI sent in stderr: “” while reading response header from upstream, client: 192.168.1.2, server: localhost, request: “GET /admin/ HTTP/1.1″, upstream: “fastcgi://127.0.0.1:8080″, host: “192.168.1.129″
2009/03/25 23:26:05 [error] 17966#0: *6 FastCGI sent in stderr: “Traceback (most recent call last):
File “/usr/lib/python2.5/site-packages/flup-1.0.1-py2.5.egg/flup/server/fcgi_base.py”, line 558, in run
protocolStatus, appStatus = self.server.handler(self)
File “/usr/lib/python2.5/site-packages/flup-1.0.1-py2.5.egg/flup/server/fcgi_base.py”, line 1116, in handler
result = self.application(environ, start_response)
File “/usr/lib/python2.5/site-packages/django/core/handlers/wsgi.py”, line 243, in __call__
response = middleware_method(request, response)
File “/usr/lib/python2.5/site-packages/django/contrib/sessions/middleware.py”, line 35, in process_response
request.session.save()
File “/usr/lib/python2.5/site-packages/django/contrib/sessions/backends/db.py”, line 52, in save
session_key = self.session_key,
File “/usr/lib/python2.5/site-packages/django/contrib/sessions/backends/base.py”, line 152, in _get_session_key
self._session_key = self._get_new_session_key()
File “/usr/lib/python2.5/site-packages/django/contrib/sessions/backends/base.py”, line 144, in _get_new_session_key
if not self.exists(session_key):
File “/usr/lib/python2.5/site-packages/django/contrib/sessions/backends/db.py”, line 25, in exists
Session.objects.get(session_key=session_key)
File “/usr/lib/python2.5/site-packages/django/db/models/manager.py”, line 93, in get
return self.get_query_set().get(*args, **kwargs)
File “/usr/lib/python2.5/site-packages/django/db/models/query.py”, line 304, in get
num = len(clone)
File “/usr/lib/python2.5/site-packages/django/db/models/query.py”, line 160, in __len__
self._result_cache = list(self.iterator())
File “/usr/lib/python2.5/site-packages/django/db/models/query.py”, line 275, in iterator
for row in self.query.results_iter():
File “/usr/lib/python2.5/site-packages/django/db/models/sql/query.py”, line 206, in results_iter
for rows in self.execute_sql(MULTI):
File “/usr/lib/python2.5/site-packages/django/db/models/sql/query.py”

尝试将数据库换成sqlite3,也是这个现象。google了一下,有人碰见过类似问题,但这个问题涉及的面太广,没有说出解决方案,只能靠自己了。准备第二天再来解决,关机休息。

第二天,机器重新启动之后,很奇怪,admin没有问题了。nginx首先自动启动,然后再手工启动fastcgi,前面好像顺序不对,不知道是不是这个理由。

分类: django, linux 标签:

python 下载 网站文档

2009年3月20日 roboter 没有评论

想下一个PIL的手册,PIL没有提供下载链接,就准备自己抓一把。发现一个python的工具

在python的Tools/webchecker目录下有一个工具websucker.py,直接如下执行:

python websucker.py http://www.pythonware.com/library/pil/handbook/index.htm
 
手册下来了,内容很完整,只是css和图片不见了。
 
完整的下载还是使用下面的wget工具,只是需要在linux下面。如果是windows,还需要下载一个windows版本的wget
网站下载工具 wget
分类: linux, python 标签:

GAE static 文件压缩

2009年3月14日 roboter 没有评论

《高性能网站建设指南》中的第四个原则就是需要压缩组件,为此考察了一下GAE的情况。在GAE FAQHow do I serve compressed content?声明如下:

Google App Engine does its best to serve gzipped content to browsers that support it. Taking advantage of this scheme is automatic and requires no modifications to applications.

We use a combination of request headers (Accept-Encoding, User-Agent) and response headers (Content-Type) to determine whether or not the end-user can take advantage of gzipped content. This approach avoids some well-known bugs with gzipped content in popular browsers. To force gzipped content to be served, clients may supply ‘gzip’ as the value of both the Accept-Encoding and User-Agent request headers. Content will never be gzipped if no Accept-Encoding header is present.

意思是GAE自动对js,css等文件进行了gzip压缩,只要客户端的浏览器支持gzip,则GAE将发送gzip压缩的文件,否则只发送原始的文件。这个过程不需要开发人员做任何处理。

经过测试,一个190K的js文件,使用firefox浏览返回的大小只有45K,减少了大概70%-80%。和gzip压缩比较起来,js内容精简的效果差了很多,js内容的精简一般只能减少20%左右。

分类: GAE 标签:

python byte unicode

2009年2月21日 roboter 没有评论

word中,可以将doc文件转成mht文件,如果有汉字,则每个汉字转成unicode,再将unicode值转化成字符串进行保存,这样整个mht文件都是ascii编码。

wps也有这个转存mht的功能,只是将汉字转成utf8进行保存。这两种方式都没有什么可说的,但是word里面的公式是转成gif文件进行保存,而wps里面的公式是转成wmf格式,除了IE浏览器支持wmf外,其他的浏览器基本都不支持。而且在网络上针对gif的处理是很方便的,wmf处理起来相对麻烦一些。

为了转换unicode的ascii编码,了解一下byte string和unicode是很有必要的

python编码的概念:  http://315ok.org/boke/pythonbianmajieyi

word的ascii编码有一个值如下:

&#39064;

其中的39064 == 0×9898,这个byte string对应的汉字就是’题’

str = u’题’

str的byte string是’u9898′

现在就需要需要把一个数字编码 转换成Unicode,python提供了一个函数unichr(),ascii字符使用chr()函数。如果反过来转换,则可以使用ord().

 

收录了一下hex和byte string的转换公式,从这里http://code.activestate.com/recipes/510399/得来:

“”"
HexByteConversion

Convert a byte string to it’s hex representation for output or visa versa.

ByteToHex converts byte string “xFFxFEx00×01″ to the string “FF FE 00 01″
HexToByte converts string “FF FE 00 01″ to the byte string “xFFxFEx00×01″
“”"

#——————————————————————————-

def ByteToHex( byteStr ):
    “”"
    Convert a byte string to it’s hex string representation e.g. for output.
    “”"
    # Uses list comprehension which is a fractionally faster implementation than
    # the alternative, more readable, implementation below
    #  
    #    hex = []
    #    for aChar in byteStr:
    #        hex.append( “%02X ” % ord( aChar ) )
    #
    #    return ”.join( hex ).strip()       

    return ”.join( [ "%02X " % ord( x ) for x in byteStr ] ).strip()

#——————————————————————————-

def HexToByte( hexStr ):
    “”"
    Convert a string hex byte values into a byte string. The Hex Byte values may
    or may not be space separated.
    “”"
    # The list comprehension implementation is fractionally slower in this case   
    #
    #    hexStr = ”.join( hexStr.split(” “) )
    #    return ”.join( ["%c" % chr( int ( hexStr[i:i+2],16 ) )
    #                                   for i in range(0, len( hexStr ), 2) ] )
    bytes = []

    hexStr = ”.join( hexStr.split(” “) )

    for i in range(0, len(hexStr), 2):
        bytes.append( chr( int (hexStr[i:i+2], 16 ) ) )

    return ”.join( bytes )

#——————————————————————————-

# test data – different formats but equivalent data
__hexStr1  = “FFFFFF5F8121070C0000FFFFFFFF5F8129010B”
__hexStr2  = “FF FF FF 5F 81 21 07 0C 00 00 FF FF FF FF 5F 81 29 01 0B”
__byteStr = “xFFxFFxFFx5Fx81×21x07×0Cx00×00xFFxFFxFFxFFx5Fx81×29x01×0B”

if __name__ == “__main__”:
    print “nHex To Byte and Byte To Hex Conversion”

    print “Test 1 – ByteToHex – Passed: “, ByteToHex( __byteStr ) == __hexStr2
    print “Test 2 – HexToByte – Passed: “, HexToByte( __hexStr1 ) == __byteStr
    print “Test 3 – HexToByte – Passed: “, HexToByte( __hexStr2 ) == __byteStr

    # turn a non-space separated hex string into a space separated hex string!
    print “Test 4 – Combined  – Passed: “,
          ByteToHex( HexToByte( __hexStr1 ) ) == __hexStr2

分类: linux, python 标签:

GAE 构建索引

2008年12月26日 roboter 没有评论

针对google的文章How Index Building Works进行了翻译,在读这篇文章的时候最好先了解Bigtable的相关内容,可以参看“大表(Bigtable):结构化数据的分布存储系统”。

每一个GAE应用都是依据索引进行查询,内置的索引可以处理简单的查询,包括在单个属性上的指定类型,过滤和排序,以及在很多属性上的“等于”过滤。更复杂的查询,需要定制developer-defined indexes

实际上,我们叫它为组合索引,以别于内在类型和单个属性的索引。我们这样说是因为这些索引数据是由每个索引列的多个值组成。

当你在应用中添加一个组合索引时,必须把你已经存在的数据填充到索引中,这时候的索引才能提供查询服务。同样,当删除一个索引时,索引列必须被删除。GAE在后台运行索引构建流程进行索引的填充和删除。

本文描述了索引如何排列,索引创建流程,以及常见问题。

索引排列

索引数据存储在四个bigtables中,被所有应用共享。前三个表存储内在类型,单个属性的升序,降序索引数据,最后一个表存储组合索引数据。

索引列的索引数据存储在bigtables的列名称中,包括app id, kind, key以及索引中额外的数据。内置的单个属性索引的额外数据包括属性名和值,内置的类型索引则没有额外数据。

组合索引中的额外数据包含了在索引定义中各个属性的值,如果指定了祖先的话,则包含祖先。属性名称省略,可以节约空间,因为索引定义中已经包含了属性名称。但是,组合索引列中包含了一个索引id,用来区分不同的组合索引恰好在同样的顺序下具有同样的属性值。

欲了解更多关于索引排列,请看Google I/O 下描述的Under the Covers of the Google App Engine Datastore

索引创建和删除

当你定义好一项新的索引,并要求我们创建时,我们按照下列步骤进行:

  1. 增加索引定义到应用中。
  2. 标识索引正在构建(Building),这样就告诉了数据存储,需要更新所有的写入,但是还不能用它进行查询。
  3. 映射存在的实体,将其填充到索引中。
  4. 标识索引正在服务(Serving),这样该索引就可以用于查询了。

删除索引几乎是相同的过程:

  1. 标识索引正在删除(Deleting),这样告诉数据存储,忽略该索引的查询和写入
  2. 删除索引列
  3. 删除索引的定义

当一个实体创建或删除,所有和该实体相关的索引列必须更新。但是,当一个实体更新时,如某些属性改变了,则仅仅更新和这些属性相关的索引。

另外,这些组合索引的处理是自动的。当一个实体需要保存或者删除,数据存储系统根据上面的规则找到相关索引,并进行更新。

由于索引更新的高效和自动化,索引构建流程可以简单重复的使用。要建立或者删除索引,流程会映射一次应用所有的实体。对于每个实体,流程使用数据存储系统在一个事务中进行读,写,保持不变。数据存储系统检测Building和Deleting状态的索引,更新相关的索引列。

并行工作

索引构建流程在并行地渐进建立和删除索引,这样可以使不同应用的索引可以在同一时间创建和删除。也可以让同一个应用里面的不同索引同时创建或者删除。最后,如果流程当掉之后,可以设立检查点恢复工作。

工作流程保存了一份在所有应用中将要删除或建立的索引列表。每一个应用的数据分成了多个碎片(shards)。当一个工作器空闲时,它查询这个列表,借用一份碎片的数据,映射碎片中的实体,象上面所说的那样填充索引列。如果在借用期到了,工作器还没有做完,则工作器放弃工作,丢弃部分完成的工作。该碎片(shards)可以再被其他工作器使用。

我们已经实现了几个不同的碎片数据机制:首先是Bigtable tablet,其次是在tablets内部,这两种方法说明如下。

以tablet进行分割

令人惊讶的是,分割一个应用的实体成为碎片不是很容易的。最理想的情况是,工作流程每N列询问一次Bigtable,从应用的第一个实体开始,到最后一个实体结束。这些将是分割点,用以区分每一份碎片。

然而,Bigtable并不打算提供这样的操作方式。于是我们提供了一个近似的方法,Bigtable按照相临的列把数据进行分块,这些块叫做tablet,它能够在运行的时候在不同的tablet服务器上进行分割,合并,移动等。Bigtable知道tablet的开始和结束列,所以我们把每一个tablet标为一个碎片(shard)。

不幸的是,tablet受限制于数据大小,所以列(实体)的数目在不同的tablet中是不同的。填充索引数据的时间更多依赖于实体的属性数目,而不是实体大小,所以不同的tablet 碎片花费的时间完全不同。在具有很多列的tablet中,工作器经常超过它的借用期,索引的删除(deleting)或者创建(building)状态会保持很长时间。

在tablets内进行分割

为了解决上述问题,我们最近增加了大碎片(shard)的分割功能。当一个工作器发现它在一块碎片上的借用期即将到期的时候,它放弃这个工作,将碎片分割成n个小碎片,每一个小碎片包含了原始碎片的列范围和两个碎片参数:n,每小片都相同。k,从0到n-1的范围。

当一个工作器取走带有分割参数的碎片时,它映射到碎片列范围中的所有实体,通常,它会列举每一个实体,计算实体key的hash值,仅仅当实体的hash值等于k%n时,它才填充索引。

交替设计可以用于填充每k个实体,这样变得很简单。但是有可能会遗漏某些实体,因为在这个处理过程中,应用可能会增加或者删除实体。

必须强调的是,在分割的时候,碎片的列范围是不会改变的。工作器依然扫描列范围内所有的实体,这个扫描相对于读写索引来说是很便宜的。进一步说,磁盘的大小比磁盘定位要便宜很多。所以Bigtable扫描比随机访问一个特定的列进行读写要便宜很多。

FAQs

下面是关于一些索引创建和删除的常规问题(如果你比较好奇怎样给你的应用指定索引,可以访问我们的文档

Q.为什么我的索引保持Building或Deleting状态那么长的时间?

A.在过去,通常是工作器中的碎片太大,以至于在碎片的借用期内无法完成。为了解决这个问题,我们首先增加了借用期限,现在我们可以将tablet分割成碎片,索引创建仍然需要一点时间,但是现在比以前快了许多。

Q.为什么我的索引标为Error状态?

A.大概是exploding indexes(爆炸索引),有时候,我们不得不手工标记索

分类: GAE 标签:

GAE大实体,激增的索引

2008年12月25日 roboter 没有评论

翻译自google的文章:http://code.google.com/intl/zh-CN/appengine/docs/datastore/queriesandindexes.html#Big_Entities_and_Exploding_Indexes

除了Text or Blob 属性外,实体中的如下属性都会至少加到一个索引表中,包括缺省提供的简单索引的属性,以及在index.yaml 文件中定义的索引中声明的属性。实体中的每属性都有一个值,属性所在的简单索引中会存储一次属性值,在自定义索引中具有该属性的每一个索引也都会存储一次。当属性改变的时候,这些索引实体都将被更新。所以,如果有很多索引指向一个属性,则执行put()更新数据所花费的时间会多一些。

为了阻止更新一个实体花费太多的时间,datastore限制了单个属性所能具有的索引数目。这个限额是很大的,大部分应用将不会注意到它。然而,有一些情况你可能会遇到他,例如,一个具有很多很多单值属性的实体可能会超越索引限额。

多值属性,如 listListProperty,在一个索引中会存储每个值。具有很多很多值的单个属性的实体也会超越索引限额。

指向多值属性,具有多个值的自定义索引,只需要很少的几个值就可以变得很大。为了完全记录这些属性,索引表必须包含每一个属性的每一个值的排列组合。例如,下面的索引包含了MyModel类型的实体,xy 两个属性:

indexes:
- kind: MyModel
properties:
- name: x
- name: y

下列代码创建了一个实体,x属性有2个值,y属性有2个值:

class MyModel(db.Expando):    pass

e2 = MyModel()e2.x = ['red', 'blue']e2.y = [1, 2]e2.put()

为了表现这些值,索引必须保存8个值,x和y的内置属性都需要有两个值,x和y的组合(2 X 2)。list值很多,则意味着索引需要存储非常多的值。你可以把一个指向多值属性、多个值的索引称作“爆炸索引”,只需要很少的一些值,就会变得很多。

如果一个put()操作导致索引实体超越限额,则调用失败,产生BadRequestError异常。如果有一个实体已经超越了限额,则创建新索引的时候,将会失败,在Admin Console上显示该index处于“Error”状态。

为了处理“Error”的索引,首先从你的index.yaml文件中删除该索引,运行appcfg.py vacuum_indexes。然后,改良索引定义以及相关的查询,或者删除导致“爆炸索引”的实体,最后,保存索引到你的index.yaml文件中,运行appcfg.py update_indexes。

避免“爆炸索引,你可以避免使用list属性的查询,象上面所说的,也包括了如下的查询:降序排列,多种排序方式,等于和不等于的组合过滤,以及祖先过滤。

分类: GAE 标签:

ie6无法访问cookie

2008年10月27日 roboter 没有评论

在内部网用django+apache建了一个站点,用ie6无法登陆,提示浏览器不允许cookie,但是使用firefox可以登录。刚开始还以为是settings.py中没有设置SESSION_COOKIE_DOMAIN导致,但是加上了也不行。google了一堆,发现在ie6下有很多cookie的问题,牵涉到跨域的问题。解决的办法就是采用p3p的方法,开始Google p3p,在http://www.yxl.cn/Info/20060302,212041,5095.html大致了解了p3p的概念。需要在网站上放置一个p3p.xml的文件,或者在djiango的respon中加入p3p的CP代码。ibm有一个工具可以编写p3p.xml,但是用java写的,估计还得下载jdk之类。感觉过于麻烦,放弃,在网上google p3p的CP代码,看是否有通用的,发现了CP=”CAO PSA OUR”,这个代码的意思就是告诉浏览器,我不需要p3p,浏览器就可以不用考虑p3p创建cookie了。

感觉很奇怪,那么要p3p干什么?用户在本地浏览器的设置也不起作用了。ie6不是多此一举吗?firefox则根本不考虑p3p。

同时在网上google了一个django的解决方案:http://www.djangosnippets.org/snippets/1084/,创建了一个Middleware,这样就不用在每个view中加入p3p的说明了。其中的CP代码换成”CAO PSA OUR”即可。

P3P_COMPACT = ‘CP=”CAO PSA OUR”‘
class MiddlewareResponseInjectP3P(object):
    def __init__(self):
        self.process_response = self.inject

    def inject(self, request, response):
        response['P3P'] = P3P_COMPACT
        return response

分类: django 标签:

python 读取ini文件

2008年10月21日 roboter 没有评论

python包含了一个ConfigParser模块,读取ini配置文件比较方便。以前一直都用它,最近希望使用ConfigParser打开utf8格式的配置文件,但是ConfigParser无法识别BOM的三个字符串。也就是不支持utf8。

google了一下,找到一个很方便的模块ConfigObj,它的读写全部基于unicode进行,所有内容形成一个字典。在存盘时,可以指定文件的编码方式。

http://www.voidspace.org.uk/python/configobj.html

示例如下:

fp = ConfigObj(inifile,encoding=’utf8′,default_encoding=’utf8′)

tags = fp['tag'] 

分类: linux, python 标签:

django apache配置

2008年9月30日 roboter 没有评论

不让django处理media目录

Alias /media /home/……/django/contrib/admin/media
<Location “/media/”>
    SetHandler None
</Location>

<LocationMatch “\.(jpg|gif|png)$”>
    SetHandler None
</LocationMatch>

报错

Invalid command ‘Alias’, perhaps misspelled or defined by a module not included in the server configuration

原因:没有安装alias_module

加上LoadModule alias_module modules/mod_alias.so 通过

分类: django 标签: