存档

‘python’ 分类的存档

django admin界面处理

2009年4月15日 roboter 没有评论

django的admin很强大,可以很方便管理后台数据。近期的一个网站需要处理一堆关联的数据,如果简单使用admin来管理,会碰到一些问题。

情形如下:有A和B两个model

class A(models.Model):
    …

class B(models.Model):
    a = models.ForeignKey(A)
    …

在admin界面中A比较好编辑,在数据量不多的时候,添加B也方便。但是如果A有了几千条数据,添加B的时候要从这么一堆A数据中选择一条,从可用性和系统性能方面来说都是是根本不可能的。于是django admin提供了raw_id_fields字段,ForeignKey字段使用了input编辑框,用户需要手工输入A对象的id即可,或者在弹出的对话框中对A对象集合进行筛选。

这样处理感觉不够方便,数据维护人员需要记住A的id,这很容易填错id。不希望让维护人员了解这些ID,所以就希望能够在A对象的列表界面加一个“添加B对象”字段,当点击这个字段的时候,即可调出B对象的添加界面,django admin支持这种自定义字段,在A对象中如下设置即可:

    def new-B(self):
        return u’<a href="/admin/xxapp/B/add/?a=%d">新建 B</a>’  %  self.id
    new-B.allow_tags = True

通过这种自定义的方式可以添加很多操作,链接会带到任何想执行的功能。

B对象的添加界面出来之后,不希望还要了解A对象的id,因为这是从一个A对象发起的添加操作。所以需要把A对象ID传到B的添加界面中。参数的传递只能通过GET进行了,考察了django.contrib.admin.options,他是支持GET参数的,于是就这样把A对象的ID细节给隐藏掉了。如果怕用户不小心修改了A对象的ID,则可以使用javascript将这个input编辑框给disable掉。

django admin支持添加css和javascript:如下例:

    class ArticleAdmin(admin.ModelAdmin):
        class Media:
            css = {
                "all": ("my_styles.css",)
            }
            js = ("my_code.js",)

B添加完成之后,还希望继续添加另外一个B,也是基于同样的A对象,点击“保存并增加另一个”,这时候GET信息丢失了,A对象ID没有了。第一反映是希望用javascript把“保存并增加另一个”的链接加上GET信息,查看了页面的源代码,是一个submit的操作,没有链接可以修改的。

input type="submit" value="保存并增加另一个" name="_addanother" /

还是到服务端来考察,在django.contrib.admin.options中查找_addanother,在response_add函数中针对_addanother进行了处理,于是事情就简单了,在B的ModelAdmin对象中重写response_add函数:

def response_add(self, request, obj, post_url_continue=’../%s/’):       
        if request.POST.has_key("_addanother"):
            from django.utils.translation import ugettext as _
            from django.utils.encoding import force_unicode
            from django.http import HttpResponseRedirect
            opts = obj._meta
            pk_value = obj._get_pk_val()           
            msg = _(’The %(name)s "%(obj)s" was added successfully.’) % {’name’: force_unicode(opts.verbose_name), ‘obj’: force_unicode(obj)}           
            self.message_user(request, msg + ‘ ‘ + (_("You may add another %s below.") % force_unicode(opts.verbose_name)))

            #新增加代码,记录下GET的信息
            getinfos = request.GET.items()
            gets = ‘?’
            for info in getinfos:
                gets += ‘%s=%s&’ % (info[0],info[1])
            path = request.path + gets

            return HttpResponseRedirect(path)
        return super(admin.ModelAdmin, self).response_add(request,obj,post_url_continue)

这样GET信息就可以保存下来了。

查看了django的最新版本,GET信息还是没有保存,这个不应该,提了一个ticket上去。

分类: django, python 标签:

python 图片处理

2009年4月8日 roboter 1 条评论

有一堆gif图片,需要处理,python有一个PIL库,处理起来很方便,但是转换的效果很有问题。如: 这一张透明的gif图片,使用简单的保存语句:

from PIL import Image

im = Image.open(’9.gif’)
transparency = im.info['transparency']
im.save(’output.gif’ ,transparency=transparency )

得出的output.gif为 ,多了一些乱七八糟的点。怀疑是我的windows系统环境有问题,然后拿到了ubuntu系统上测试,也是如此,不甘心,在ubuntu上下载了一个python 2.5.4,再下载了PIL的源码进行编译,现象依旧。然后再跑到国外的主机上进行测试,也是一样,不过转换出来的大小都不太一样,有几十个字节的差异。

在open之后,我立即打印了im的数据

print list(im.getdata())

按照正常的话,黑白gif应该只有0和1的点,但是发现下面有很多大于1的点:

[0, 0, 0, 0, 192, 48, 30, 30, 241, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 100, 0, 0, 90, 0, 0, 100, 1, 0, 100, 2, 0, 107, 1, 0, 90, 1, 0, 100, 1, 0, 100, 2, 0
, 107, 2, 0, 90, 2, 0, 100, 0, 0, 0, 1, 1, 1, 1, 1, 0, 3, 0, 104, 0, 0, 4, 100, 0, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0, 2, 100, 6, 0, 60, 0, 0, 0, 0, 1, 0, 0, 0, 1, 4,
100, 9, 0, 2, 100, 10, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 60, 4, 100, 13, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 0, 100, 15, 0, 60, 90, 4, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 100,
17, 0, 101, 3, 0, 105, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 131, 0, 0, 89, 90, 0, 0, 1, 0, 0, 0, 1, 0, 0, 7, 0, 101, 2, 0, 105, 8, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 13
1, 3, 0, 1, 101, 2, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 131, 2, 0, 1, 101, 2, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 131, 2, 0, 1, 101, 2, 0, 105, 10, 0, 100, 20, 0, 100, 22,
0, 131, 2, 0, 1, 101, 2, 0, 105, 10, 0, 100, 20, 0, 100, 23, 0, 131, 2, 0, 1, 100, 2, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

尝试将大于1的点清0,再putdata回去,结果是干净了一点,但还有一些污点,可能本来是一些0的点被染成了1。

该gif图片的格式为GIF89a,转存之后为GIF87a。

我又尝试了一些非透明的gif,这样的转存没有问题。难道是PIL对透明gif处理有问题?google了很多文章,都没有发现什么解决方案或者类似的问题,老外写的文章PIL Tips: Converting Between PNG and GIF,倒是有很多例子,不过好像没有碰到我的这个问题。

————————————————————————

没辙了,看看有没有其他的图形库。发现了imagemagick。有python接口,提供了命令行工具。于是在ubuntu上用sudo apt-get install python-pythonmagick安装,下了一堆包,安装完成,在site-packages目录没有发现任何新东西,不知道给装到哪里去了。当然就无法import PythonMagick了。罢了,还是手工编译安装吧。

imagemagick很顺利的编译安装,听说python接口手工安装非常麻烦,也不用python接口了,直接使用命令行进行处理。看了大量的例子帮助,明白了一些基本用法,直接在命令行输入下列指令:

convert 9.gif output.gif

这回成功了,output.gif和9.gif图片一样的。但是在将png转换为gif的时候报错:

convert    gtk1.png  gtk1.gif
convert: no decode delegate for this image format

google了一下,应该是少了一些部件。需要到(http://www.imagemagick.org/download/delegates/)下载所缺少的库进行安装,之后imagemagick需要再重新configue ,make install.

分类: linux, python 标签:

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 标签:

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 标签:

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 标签:

xmlrpclib base64编码

2008年8月27日 roboter 没有评论

在xmlrpclib中,需要传送二进制的数据,因此使用了Binary Objects来打包,写了如下两个函数:

def encodebindata(data):
    out = StringIO.StringIO()
    bin = xmlrpclib.Binary()
    bin.data = data
    bin.encode(out)
    data2 = out.getvalue()
    return data2

def decodebindata(data):
    bin = xmlrpclib.Binary()
    data1 = bin.decode(data)
    return bin.data

在调用decodebindata函数解码的时候,老是出错,提示”binascii.Error:  incorrect padding”之类的。看了一下xmlrpclib.py里面的Binary 类定义:

def decode(self, data):
        self.data = base64.decodestring(data)

def encode(self, out):
        out.write(”<value><base64>n”)
        base64.encode(StringIO.StringIO(self.data), out)
        out.write(”</base64></value>n”)

Binary的编解码其实用到的是base64的decodestring和encode,感觉不太匹配,base64中,encode应该和decode配对,decodestring和encodestring配对。因此尝试了一下直接使用base64来打包,不使用xmlrpclib的Binary Objects。重新定义两个函数如下:

def encodebindata(data):
    out = StringIO.StringIO()
    bin = StringIO.StringIO(data)
    base64.encode(bin,out)
    data2 = out.getvalue()
    return data2

def decodebindata(data):
    out = StringIO.StringIO()
    bin = StringIO.StringIO(data)
    base64.decode(bin,out)
    data2 = out.getvalue()
    return data2

经过测试,没有任何问题了

xmlrpclib的Binary Objects打包之后就是xml形式的数据了,可以直接传送了。不能打包之后立即解包。

分类: linux, python 标签:

python中动态创建类

2008年8月21日 roboter 没有评论

动态创建类对象的方法很方便,用getattr可以得到类的方法地址,然后就可以直接调用了,这就叫自省。

最近玩了一下python的xmlrpc,看了limodou的文章[Python]如何在Google APP Engine中进行xml-rpc的处理,很容易在app engine上搭建起了xml rpc环境。但是有一点限制,仅仅支持函数的查找,不支持类对象,比如期望像math.power(2,8)之类的调用。

因此就想扩展一下,支持类对象的动态创建,google一下之后,发现ibm的文章《Python 中的元类编程》http://www.ibm.com/developerworks/cn/linux/l-pymeta/index.html,感觉很恐怖,太麻烦了。limodou用了一个globals()来列出所有的模块列表,打印了globals()的返回结果后,发现有当前定义的类的模块。于是就有了下面的代码

mm = m.split(’.')
mymodel = globals().get(mm[0])
if mymodel != None:
    if len(mm) == 2:
        x = mymodel()  #在此实例化类对象
        f = getattr(x,mm[1])
    else:
        f = mymodel

这样就可以把”obj.function()”执行起来了

分类: linux, python 标签:

python 调用C++

2008年4月27日 roboter 没有评论

python可以调用C、C++写的动态库,C++也可以调用python程序,二者可以进行很好的交互。

开源代码中,有很多库提供了python的接口,如dbus,有一个dbus-python模块,就是使用python封装了dbus的接口。在一些复杂的算法设计中,一般都需要使用C/C++编写,可以获得比较好的性能,对外则可以提供python接口。

python调用C程序的步骤很简单,主要看python自带的python 手册,直接看“Extending and Embedding”一节,首先上来的是一个简单例子。python与C的接口工作主要是参数格式的转换,python定义的数据格式和C的数据结构需要互相转换。可以参考IBM的文章http://www.ibm.com/developerworks/cn/linux/l-pythc/index.html

每个python对象都有一个引用计数,当引用计数为零时,python就会删除这个对象。因此在C中创建了python对象时,可以使用Py_INCREFPy_DECREF等宏来控制。

在linux下,编译成so库,python可以直接import。windows下,需要将dll的后缀修改成pyd,python才能识别。

分类: python 标签:

python 排序

2008年3月17日 roboter 没有评论

一个类集合需要排序,在一般C++中需要写好几行代码,而且很多代码都还不是直接的逻辑判断。

如:class a,b,c,d,e…., 一般需要两个for循环,两个下标变量,判断完成还需要更改位置,而我们最关心的主要是判断比较函数,其他代码都不是我们愿意编写的。在STL中,有标准sort函数,只需要调用这个接口就可以帮我们把其他步骤都省略了,sort(v.begin(),   v.end(),   mycmpfunc); 

python也是同样,只需要一行代码搞定:

list1.sort(lambda i,j: comparefunc(list1,i,j))

我们主要编写comparefunc函数即可,实在省心。

STL中的比较函数参数是固定的,两个对象。而python作为脚本语言,可以传入任意参数,更加方便。

分类: python 标签: