Django community: RSS
This page, updated regularly, aggregates Django links from the Django community.
-
Django使用Uploadify组件实现图片上传
Uploadify组件上传文件很酷,可以实现文件进度上传,而且可以批量上传各种文件。好处还很多,具体详情登到官网看看文档了解吧。在同类组件中,Uploadify做的也很出色。打算在Django中用它,两个东西结合使用,也算简单,但有些细节需要记下来,以便以后重用。这次只说上传图片部分,至于上传文件,其实可以照猫画虎,而且来得会简单些,只是python程序后端写法的区别而已,前端代码Uploadify一律平等对待,图片也是文件一种特例罢了。Django使用Uploadify组件实现图片上传,可以分为两个大步骤。一:前端引用Uploadify所需要的类库和脚本样式。Uploadify会用到JQuery类库,还有自己的几个脚本和样式文件,搭配好了Django的静态文件,让Django正确解析静态文件,就算成功一半了,静态文件的配置参考先前的博客:《Django静态文件的配置》。静态文件我们统一存放在根目录的site_media文件夹下,到官网http://www.uploadify.com/下载Uploadify-2.14组件,放在site_media下的plugin,随意起名:uploadify_214,再新建个文件下upload,来存放上传的图片。前端样式脚本引用代码:<link href="/site_media/plugin/uploadify_214/uploadify.css" type="text/css" rel="stylesheet" /> <script type="text/javascript" src="/site_media/js/jquery.js"></script> <script type="text/javascript" src="/site_media/plugin/uploadify_214/swfobject.js"></script> <script type="text/javascript" src="/site_media/plugin/uploadify_214/jquery.uploadify.v2.1.4.min.js"></script>引用文件的路径算是很重要,具体静态配置决定这些。首先引用Uploadify的样式文件,然后就是先引用JQuery类库,再引用Uploadify自身脚本swfobject.js和jquery.uploadify.v2.1.4.min.jsUploadify组件初始化代码:<script type="text/javascript"> $(document).ready(function() { $('#file_upload').uploadify({ 'uploader' : '/site_media/plugin/uploadify_214/uploadify.swf', 'script' : '{%url uploadify_script%}', 'cancelImg' : '/site_media/plugin/uploadify_214/cancel.png', 'folder' : '/upload', 'auto' : false,// 'multi': true,//设置可以上传多个文件 'queueSizeLimit':20,//设置可以同时20个文件 'removeCompleted':false,// 'sizeLimit':10240000,//设置上传文件大小单位kb 'fileExt':'*.jpg;*.gif;*.png',//设置上传文件类型为常用图片格式 'fileDesc':'Image Files', 'onInit': function () {}, 'onError' : function (event,ID,fileObj,errorObj) { $('#id_span_msg').html("上传失败,错误码:"+errorObj.type+" "+errorObj.info); }, 'onSelect': function (e, queueId, fileObj) { $('#id_span_msg').html(""); }, 'onAllComplete': function (event, data) { if(data.filesUploaded>=1){ $('#id_span_msg').html("上传成功!"); } } }); }); </script>初始化脚本,有几个关键的参数需要说明一下:uploader是组件需要flash编译文件,里面封装了Uploadify核心的处理程序。script是后端上传文件程序的url,这个是后面说的,需要自己写。folder是上传文件的目录,这里我们不计划使用它,随便写一个充数。前端html代码<h1>Uploadify组件上传方式</h1> <div class="demo-box"> <input id="file_upload" type="file" name="Filedata"> <div id="file_uploadQueue" class="uploadifyQueue"></div> <p><a href="javascript:$('#file_upload').uploadifyUpload()">上传图片</a> <a href="javascript:$('#file_upload').uploadifyClearQueue()">取消上传</a> </p> <p><span id="id_span_msg"></span></p> </div>二:写好后端图片上传的方法。如果刚开始就把写好的上传程序和Uploadify结合,也许不是很明智的做法,因为过程中遇到问题,我们不很确定是后端程序的bug还是Uploadify的配置错误,所以建议先把写好的后端上传程序,用传统的上传方式,去测试,把程序调试好了,再和Uploadify结合,这样就会很清楚是那块出现问题了。所以我们先写个通用的上传函数_upload,用传统的上传方式测试它,该函数:def _upload(file): '''图片上传函数''' if file: path=os.path.join(settings.MEDIA_ROOT,'upload') file_name=str(uuid.uuid1())+".jpg" path_file=os.path.join(path,file_name) parser = ImageFile.Parser() for chunk in file.chunks(): parser.feed(chunk) img = parser.close() try: if img.mode != "RGB": img = img.convert("RGB") img.save(path_file, 'jpeg',quality=100) except: return False return True return False这个程序接收一个Files对象,在内存里处理保存好图片,程序就几行代码就不解释太多了。大体是先构造一个物理地址用于保存图片,再把内存里的图片信息存入img临时变量中,判断图片的模式,如果不是RGB,转换,保存成jpg格式,返回True,失败返回False。该函数测试通过了,能完成保存图片的使命,最后就是写Uploadify需要的函数uploadify_script@csrf_exempt def uploadify_script(request): response=HttpResponse() response['Content-Type']="text/javascript" ret="0" file = request.FILES.get("Filedata",None) if file: if _upload(file): ret="1" ret="2" response.write(ret) return responseUploadify使用uploadify_script函数,通过Get方式把图片控件的信息提交给该函数,函数返回"text/javascript"的内容类型,如果成功写入字符1,否则写入非1字符。页面的图片控件命名Filedata,Django通过file = request.FILES.get("Filedata",None)获取控件的图片信息,如果不是空的,就传递给刚才说的通用函数_upload,保存图片。整个过程算是完结了,过程中值得注意的:1 常常出现IO Error,如果我们已经测试_upload和uploadify_script后端程序,他们都没有错误,很多程度上是因为前端的Uploadify初始化脚本的问题,确认Uploadify几个关键的参数能不能正确解析,或者是静态文件配置没成功造成的。2 Forbidden (403)这是Django引发的,Django1.3引进了CSRF,我们需要进行一些处理,给uploadify_script一个装饰器@csrf_exempt,记住这个很关键,很折腾人。3 cannot write mode P as JPEG,这个是后端上传程序的错误,是因为上传了非jpg类型的图片,我们需要需要转换成RGB,再保存,上面已经提过。好了不废话,例行给一个例子,看源码就明白了,本地浏览地址:http://127.0.0.1:8000/uploadify/。 -
Ubuntu下Nodejs开发环境快速搭建
Nodejs很火,在Ubuntu下搭建它的开发环境尝尝鲜,有一个捷径,它能让系统自动帮你安装所需要的东西,我们生成一段shell脚本,让它来完成以下工作: 安装git下最新的node,node包管理器,Forever和Cloud9IDE工具(可选),mongodb 10gen;脚本的正常运行需要比较新板的Ubuntu,而且需要联网,因为它会连接网络去下载所有的依赖包顺序安装。#!/bin/sh # Update System echo 'System Update' apt-get update echo 'Update completed' apt-get install libssl-dev git-core pkg-config build-essential curl # Clone Node.js echo 'Clone Node.js' cd /usr/src git clone https://github.com/joyent/node echo 'Node.js clone completed' # Install Node.js echo 'Install Node.js' cd node ./configure && make && make install echo 'Node.js install completed' # Install Node Package Manager echo 'Install Node Package Manager' curl http://npmjs.org/install.sh | sh echo 'NPM install completed' # Install Forever echo 'Install Forever' npm install forever echo 'Forever install completed' # Install Cloud9IDE echo 'Install Cloud9IDE' git clone git://github.com/ajaxorg/cloud9.git echo 'Cloud9IDE install completed' # Install MongoDB echo 'Install MongoDB' sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10 echo "deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen" >> /etc/apt/sources.list sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10 sudo apt-get update sudo apt-get install mongodb-10gen echo 'MongoDB install completed.'安装方法:$ cd ~/ $ nano -w node.sh把以上代码粘贴到node.sh文件里,ctrl+o 保存,ctrl+x 退出nano。如果你没有安装nano,请google一下安装吧。然后执行脚本:$ chmod a+x node.sh && sudo ./node.sh如果网速足够快,一会功夫即可完成安装。等安装完毕,我们来个测试:mkdir node_project cd node_project nano -w server.js粘贴以下著名的代码:var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(1337, "127.0.0.1"); console.log('Server running at http://127.0.0.1:1337/');ctrl+o 保存,ctrl+x 退出nano,尝试跑它 :node server.js在浏览器中打开 :http://127.0.0.1:1337,看到久违的Hello World了吧? -
悲剧的辉腾[转]
一大哥花了256万买了辆W12 缸6.0的大众辉腾, 杯具了。某日,大哥进停车场,正在自动泊车中,管理员冲他喊道:“喂,开帕萨特的小心点,别把边上的新宝马320给撞了,你赔不起”,大哥一怒吼到 “老子的车够买他10辆了”某日,大哥进加油站,一不留神,加油小妹的93号枪就对准开加了,大哥汗都下来了,吼到”老子是要加 97的,谁让你自作主张加93了.” 小妹好心的回说“大哥,帕萨特加93的绝对没事,我每天都加多少帕萨特,93的省钱,不是奔驰宝马没必要加97”某日,大哥去夜店泡妞,看中一正妹后,相约一并外出霄夜,兼后半场,正妹看大哥气质不凡,跟他走向停车的地方,一见大哥的辉腾,正妹扭头就走,并说到“开桑塔纳还好意思约我吃霄夜,早知道跟刚才开凯美瑞的走了。某日,大哥宴请一高官,开车到其家接他,大哥恭敬的把车门打开,高官走近一看,说道:“我还是让司机把A6开出来吧”某日,大哥到一处接朋友,此小区门口黑车众多,大哥在车上等朋友之际听到黑司机们议论,“这么好的车也出来拉活啊”,另一位说到“可能单位的吧,不过帕萨特怎么也得百公里8个油吧”,大哥摇下车窗怒吼之“老子百公里得17个油”某日,大哥一朋友之重要朋友结婚,要借一重量级头车,大哥厚道之人,虽爱车之心无比,也大方出借,事后朋友还车,大哥自豪问到“怎么样,让你在朋友面前长脸了吧”,朋友叹道“别提了,朋友非说这是一老款的帕萨特太不拉风,最后又花钱租了一辆当前的红色跑车当婚车,你的车就排到婚车队最后一个专门接送上了年纪的老人家和儿童了。”某日,大哥停完车正往外准备走的时候,听见身后两个年轻人的对话,一人说到“快看,哇塞,辉腾啊!”,大哥心中一片舒坦,终于有识货之人,正爽之际,听到另一年轻人说“晕,还真有傻子买它啊。” -
无聊无题的无稽之谈
不记得什么时候开始有打开Django的Timeline观望的习惯了,思维有点乱,Google的Chrome才是真的版本帝,每天几十到几百条,甚者千余条bug Fixed,现在安装金丝雀,几乎每天都有更新,而且一两个月幸运才能逮到一个两个bug,这样的效率和质量让人羡慕不已。Django的Timeline上,每天都能看到几十条的Bug Fixed。平均应该有20条以上吧。嗯,用平稳来形容吧,再仔细看看Fixed了什么东西,都是一些琐碎的完善和扩展,没有太多的想要看的:想看到的比如:在ORM QuerySet上进行一些运算再filter再order;或者增强Forms的易用性,解决csrf通俗处理等等之类的。再看看Github上的Rails,也差不多的情形,都马不停蹄的进行中,以上说的是参与度。两边的阵容都很豪华,有不少的名人。我喜欢Django,是因为Python语言简洁成熟,语言风格适合本人。而Django是以程序员的法则去引导开发,玩Django的或多或少为一些细节困扰,因为我们常常碰到市场的需求,碰到非技术人的要求,常常为他们那些看似无理的东西,感到愤怒,到最后想想也不无道理,有时候有得折腾。所以在界内,Django不能成为web framework的标准。我倒觉得Rails倒是人们寻找的那个标准,没有深入,只是偶尔看看,不难理解,人总有感知的,谈谈想法而不是真相。他们有相似的地方,Rails有一种架势,不管黑猫白猫,能抓到老鼠就是好猫。Rails的大方向很准,有人心有市场,而且常常具备一些亮点,不足的是平台上的一致性还需要点时间发展。这两个都是完美的框架。同一时期,微框架也很出位,如:flask bottle,sinatra 等等,特点很多,易上手,性能出众,好扩展,插件丰富。框架本身就一千几千行的代码,实现的只是核心必要的功能。要想做一件东西出来,需要找插件来辅助,或可以造轮子,创造自己的插件。这样的框架也同样有利有弊,利:让第三方(或自己的分支)集中精力做好插件,做精品级的东西和同类插件竞争,优胜略汰,给用户争取精品中的精品;弊:选择的问题,用户精力的分散。IT发展很快,这些东西已经是前浪,一些新新的东西已经出来了。Node不是语言,大概就是借助Javascript语言,Google V8,集中一些类语言的东西,封装在一起,让用户使用javascript语言开发服务端的东西。Mozilla也有自己的javascript引擎,同时也在开发类似Node的东西。Node特点是 异步的 无阻塞的,性能极高。其下的web framework也陆续出来了,如:expressjs,geddy ,express on railway,活跃度,参与度比较高的应该是expressjs,它是sinatra 的node实现,算是一个微框架,express on railway就是从它那里引伸过来的,不过railway是类似rails的框架,参与度还不算很高。express on railway,express 的发明者都是从Rails阵营过来的,代码中常常看到Rails的身影。Geddy是个特别的框架,有点像Django,也有Rails的身影,作者最近很忙,开发进展有点缓慢,听说他正参与另一个更重要的项目。开发类似Django Rails的Node框架(或者是full-stack框架),可能需要更多的人,技术和基金。发现完善的东西为其尚早。相反微框架开发要轻松的多,所以express就很活跃。现在还是初期,相信很快就有full-stack框架出来了。 -
尽量不要使用Django select_related()
Django的select_related()在1.3.1之前(包括1.3.1)都存在性能的问题,今天使用debug_toolbar大概测试了一下,depth=1,发现性能损失了20%以上,如果不指定depth,model关系复杂的时候,可能会损失更多。select_related()对关联多的实体本身是一个很好的方案,采用了内连接,减少数据库多次发起连接动作,按理来说性能会更优,但很奇怪,测试结果却相反。自己的测试的实体集合,不采用select_related(),耗时76ms,sql连接数47,而用了select_related()后,耗时97ms,sql连接数37。 -
第二年使用Burst的VPS
第一年使用Burst的VPS,为它灵活的设置吸引,系统支持主流的Linux发行版本,如SentOS,Fedora,Debian,Ubuntu,Centoo,这么多的选择中,有喜欢的Debian,并且安装系统只需要在后台reload一下,花上几分钟的时间,一个纯净的系统就安装好了。剩下的就是自由的环境配置了。还有关键的就是学习用途,VPS的价格最具竞争价值,每个月5.95美元,买满一年,只收10个月的租金,在这个基础上,再打上7.5折,一年下来,就是300(约290)元不到。今年继续购买,发票已经下来了:VPS #1 (Virtual Private Server) - vePortal - (LOS ANGELES, CA) - (12/22/2011 - 12/21/2012) $59.51 USDPromotional Code: LOWENDLAVPS - 25.00% Recurring Discount $-14.88 USD------------------------------------------------------Sub Total: $44.63 USDCredit: $0.00 USDTotal: $44.63 USDAmount: $44.63 USDTotal Paid: $44.63 USDRemaining Balance: $0.00 USDStatus: Paid不过有个问题就是,Burst 的VPS #1 不是很稳定,有时会掉线,商业用途这点很致命,学习用途是超值的。 -
让Nginx处理Django的静态文件
上次的《Django静态文件的配置》,说的主要是针对开发环境的配置。在开发中难免要处理网站的css js image等静态文件,不用顾及性能,安全的问题,交给Django内部处理好了;但如果正式部署到服务器的时候,这样的配置就会影响到性能和安全性了,这时怎么办呢?嗯,交给Nginx处理好了。假如项目的目录结构如下:myproject--app1--app2--media----css----js----images--templates--setting.py--urls.py--manage.py--...解释:通常项目文件夹下有若干个app应用,如app1 app2我们把静态文件方在项目的根目录下,起名为media(这个可以任意起名,但顾名思义,起个明了的名字),media文件夹里分别新建 css,js,images文件夹,用他们放置样式,脚本,图片等用途。剩下的就是Django生成的settings urls manage配置文件了。这回计划在开发环境中,使用Django处理静态文件,而正式部署后使用Nginx来处理他们。首先在urls.py文件中最后加上以上代码if settings.DEBUG: urlpatterns += patterns('', url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': os.path.join(settings.SITE_ROOT,'media')},name="media"), )具体的意思是:如果是开发环境,让Django的django.views.static.serve来处理,而正式部署时,Django不做任何事情,让Nginx来处理,后面会讲到Nginx的配置问题。settings.DEBUG其实就是开发和部署的标示变量,部署的时候在settings里给DEBUG变量赋值False,让Django Templates屏蔽一切Debug;赋值True时,相反,是开启Debug,开发中出错以便查看一些错误信息。开发环境中,settings的配置如下:import osDEBUG = TrueTEMPLATE_DEBUG = DEBUGSITE_ROOT=os.path.abspath(os.path.dirname(__file__))MEDIA_ROOT = os.path.join(SITE_ROOT,'media')MEDIA_URL = '/media/'正式部署的时候,把变量DEBUG改成False即可。正式部署的时候,Nginx的静态文件配置很关键,先看代码:location ~ ^/media/ { root /home/http/django_project/myproject/; expires 24h; access_log off; }如项目实际路径是:/home/http/django_project/myproject/,那以上的配置代码会到 /home/http/django_project/myproject/ 路径找 media文件夹。一两点值得注意的:1 刚开始一直没有配置成功,原因是root的没配置正确,写成 root /home/http/django_project/myproject/media/ 了, 导致Nginx老找不到media文件夹。2 还有一个值得注意的是:location ~ ^/media/ 要和实际的静态文件夹对应哦,如果写成location ~ ^/static/ 那肯定不行的(完)晚了,洗洗睡了。 -
让Django根据自定义属性排序
刚开始开发博客的时候,本来想让博客按照阅读量,评论量,赞成数等属性,根据某个计算公式计算结果来排序,但后来因为在Django的ORM里不知道怎么写,又不想混杂一些SQL语句,所以一直没有实现。到了现在,想想通过ORM来实现,还是无法做到的。因为Django的QUERYSET里,根据几个属性的计算(如:分别求出各个属性值的比例,再求和,最后按照比例再除法或更复杂的计算)结果去filter,或order by,是无法做到的。现在想想,如果在models里,建立一个子def(自定义属性),专门负责几个内置属性的计算,返回结果。这样就相当是models实例的一个属性了,然后再在QUERYSET里排序,不就好了吗?可是仔细想想,还是不行,这样只是降低QUERYSET语句写法的复杂性,最后的order by还是取不到实例的子def(自定义属性)的返回值。最终还是回到原点了。最后,想到一个不是很地道的办法,那就是使用原生python的sorted()函数:object_list = sorted(Blog.objects.all(), key=lambda blog: blog.cir_val,reverse=True)这样就解决了。models里需要先定义一个自定义属性cir_val,根据某个算法把几个内置属性组合结果算出来。形如:def cir_val(self): return self.browse*1/5+self.comment*2/5+self.zan*3/5一时的思维掠过,我也不知道自己在写什么,总之解决了我一年来,来不及想的问题,只是不知道怎么表达问题罢了。 -
Django数据处理的优化
Django数据层提供各种途径优化数据的访问,一个项目大量优化工作一般是放在后期来做,早期的优化是“万恶之源”,这是前人总结的经验,不无道理。如果事先理解Django的优化技巧,开发过程中稍稍留意,后期会省不少的工作量。一 利用标准数据库优化技术:传统数据库优化技术博大精深,不同的数据库有不同的优化技巧,但重心还是有规则的。在这里算是题外话,挑两点通用的说说:索引,给关键的字段添加索引,性能能更上一层楼,如给表的关联字段,搜索频率高的字段加上索引等。Django建立实体的时候,支持给字段添加索引,具体参考Django.db.models.Field.db_index。按照经验,Django建立实体之前应该早想好表的结构,尽量想到后面的扩展性,避免后面的表的结构变得面目全非。使用适当字段类型,本来varchar就搞定的字段,就别要text类型,小细节别不关紧要,后头数据量一上去,几亿几亿的数据,小字段很可能是大问题。二 了解Django的QuerySets:了解Django的QuerySets对象,对优化简单程序有至关重要的作用。QuerySets是有缓存的,一旦取出来,它就会在内存里呆上一段时间,尽量重用它。举个简单的例子:了解缓存属性:>>> entry = Entry.objects.get(id=1)>>> entry.blog # 博客实体第一次取出,是要访问数据库的>>> entry.blog # 第二次再用,那它就是缓存里的实体了,不再访问数据库但下面的例子就不一样,>>> entry = Entry.objects.get(id=1)>>> entry.authors.all() # 第一次all函数会查询数据库>>> entry.authors.all() # 第二次all函数还会查询数据库all,count exists是调用函数(需要连接数据库处理结果的),注意在模板template里的代码,模板里不允许括号,但如果使用此类的调用函数,一样去连接数据库的,能用缓存的数据就别连接到数据库去处理结果。还要注意的是,自定义的实体属性,如果调用函数的,记得自己加上缓存策略。利用好模板的with标签:模板中多次使用的变量,要用with标签,把它看成变量的缓存行为吧。使用QuerySets的iterator():通常QuerySets先调用iterator再缓存起来,当获取大量的实体列表而仅使用一次时,缓存行为会耗费宝贵的内存,这时iterator()能帮到你,iterator()只调用iterator而省去了缓存步骤,显著减少内存占用率,具体参考相关文档。三 数据库的工作就交给数据库本身计算,别用Python处理:1 使用 filter and exclude 过滤不需要的记录,这两个是最常用语句,相当是SQL的where。2 同一实体里使用F()表达式过滤其他字段。3 使用annotate对数据库做聚合运算。不要用python语言对以上类型数据过滤筛选,同样的结果,python处理复杂度要高,而且效率不高, 白白浪费内存。使用QuerySet.extra():extra虽然扩展性不太好,但功能很强大,如果实体里需要需要增加额外属性,不得已时,通过extra来实现,也是个好办法。使用原生的SQL语句:如果发现Django的ORM已经实现不了你的需求,而extra也无济于事的时候,那就用原生SQL语句吧,用Djangoango.db.connection.queries去实现你需要的东西。四 如果需要就一次性取出你所需要的数据:单一动作(如:同一个页面)需要多次连接数据库时,最好一次性取出所有需要的数据,减少连接数据库次数。此类需求推荐使用QuerySet.select_related() 和 prefetch_related()。相反,别取出你不需要的东西,模版templates里往往只需要实体的某几个字段而不是全部,这时QuerySet.values() 和 values_list(),对你有用,它们只取你需要的字段,返回字典dict和列表list类型的东西,在模版里够用即可,这可减少内存损耗,提高性能。同样QuerySet.defer()和only()对提高性能也有很大的帮助,一个实体里可能有不少的字段,有些字段包含很多元数据,比如博客的正文,很多字符组成,Django获取实体时(取出实体过程中会进行一些python类型转换工作),我们可以延迟大量元数据字段的处理,只处理需要的关键字段,这时QuerySet.defer()就派上用场了,在函数里传入需要延时处理的字段即可;而only()和defer()是相反功能。使用QuerySet.count()代替len(queryset),虽然这两个处理得出的结果是一样的,但前者性能优秀很多。同理判断记录存在时,QuerySet.exists()比if queryset实在强得太多了。当然一样的结果,在缓存里已经存在,就别滥用count(),exists(),all()函数了。五 懂减少数据库的连接数:使用 QuerySet.update() 和 delete(),这两个函数是能批处理多条记录的,适当使用它们事半功倍;如果可以,别一条条数据去update delete处理。对于一次性取出来的关联记录,获取外键的时候,直接取关联表的属性,而不是取关联属性,如:entry.blog.id优于entry.blog_id善于使用批量插入记录,如:Entry.objects.bulk_create([ Entry(headline="Python 3.0 Released"), Entry(headline="Python 3.1 Planned")])优于Entry.objects.create(headline="Python 3.0 Released")Entry.objects.create(headline="Python 3.1 Planned")前者只连接一次数据库,而后者连接两次哦。还有相似的动作需要注意的,如:多对多的关系,my_band.members.add(me, my_friend)优于my_band.members.add(me)my_band.members.add(my_friend)为什么,批量处理的角度自己琢磨一下。 -
使用SSH操作远程PostgreSQL数据库
服务器安装了PostgreSQL 9.2数据库,而数据库不允许外部ip连接;手头只有个SSH账号,怎么操作建立一个数据库呢?今天做了初步的试探。之所以模拟自己的ubuntu服务器环境,因为下面的指令,会与环境有所差别,使用指令之前仔细检查实际的环境参数。数据库安装路径:/opt/PostgreSQL/9.2SSH账号:178.90.22.11rootroot123数据库的内部账号:postgres1234567开始动工了,首先在本地终端 用SSH登录到远程服务器终端:ssh root@178.90.22.11这时远程会提示数据密码,输入root123回车 完成登陆(第一次可能要自动生成一个密钥,只需回车确认即可)。这时已经成功进入远程服务器的终端,关键的时刻到了,怎么在终端,建立一个PostgreSQL数据库呢?我们需要登录到服务器的数据库控制台,才能执行PostgreSQL语句,所以先登录到数据库控制台,我们用psql指令操作:/opt/PostgreSQL/9.2/bin/psql postgres postgres诠释:psql在/opt/PostgreSQL/9.2/bin/路径下,postgres postgres是postgres账号登录到postgres 数据库(默认的名称)这时数据库要求输入数据库的密码(Password for user postgres:),输入1234567回车,成功进入数据库控制台,这时你会看到:psql.bin (9.2.1)Type "help" for help.postgres=#这时可以建立一个全新的数据库了,比如建立一个名叫2gooDB的,编码是utf-8的,模式为template0的,属于postgres账号的数据库:在#后输入:CREATE DATABASE 2gooDB OWNER postgres ENCODING 'utf-8' TEMPLATE template0;PostgreSQL指令还挺严格的,注意一条语句结尾加上分号,表示语句的结束。指令参考:http://www.postgresql.org/docs/9.2/static/sql-createdatabase.html数据建立好了,如果发现起初没有规划好,想删除刚建立的数据库 2gooDB:DROP DATABASE IF EXISTS 2gooDB;至于修改数据库,指令选项就多点了,比如:ALTER DATABASE name RENAME TO new_name;ALTER DATABASE name OWNER TO new_owner;ALTER DATABASE name SET TABLESPACE new_tablespace;....修改指令还真没有用过,以上三条指令应该好理解,确实没有把握,你只能删除后,再重新建立了。各数据库之间的切换,MySQL 是use指令,PostgreSQL是\c dbname列出该数据库的所有表信息\d查看执行一条语句耗时:\timing提示 Timing is on.select id from table1;结果:Time: 162.181 ms列出各数据库的信息(数据库名 用户 编码等信息):\l数据库已经建立好,剩下的建表,数据初始化,都交给Django来做吧。最后退出psql控制台指令:\q(完) -
对Django media和static概念的理解
早在Django 1.3时期,增加了staitc模块,之前media模块保留至今,当时项目使用Django 1.2,静态文件都使用media,习惯了用法,一直没有正式去看staitc的东西,当然项目一直没有用到static模块。Django 1.4后用了一段时间,基本知道怎么去用了。我想把当时的困惑重温一下,刚接触static的时候,最想知道的是:media和static两者到底有什么区别?或者说两者用途上有什么区别?那就说说两者的区别吧。media和static字面上理解,媒体文件和静态文件。字面上抽象确实不好理解。如果结合项目存在的东西去理解,发现概念会马上清晰起来。比如网站项目,需要css js 和图片(专属网站页面使用的),这些文件就是常说的静态文件,统归于staitc下处理;而有些文件比如:用户上传的头像,音乐,文档,图片等等,并不是网站专属的文件,而是由用户自主上传/添加的媒体文件(很广的范畴),统归于media下处理。怎么样?有例子应该很好理解吧。两者的配置,对于初学者来说都不算很容易,这两个东西不是同一时间出来的,meida出来比较早,之前media涵盖了stiatc的用途,两个东西浑然一体,要一下子分开用,总得适应吧,再者Django的静态文件和媒体文件的处理方法上相比传统框架也算比较新颖,需要使用者自己去琢磨一翻,才有自己的理解。media的使用方法,比较熟悉了,下次想说说static的用法,自己做个笔记也好。 -
简易配置Django的Static文件
Django 1.3以后,采用static方式处理静态文件,比如网站的css js images等等,而以前所谓的media改成处理网站自身以外的媒体文件了。media和static用途上容易混淆,请移步上次讲的《对Django media和static概念的理解》。如果简单使用static,配置起来会比media要少一步,下面会比较一下。说到static,不能不说说Django开发环境和部署环境的区别,Django配置文件settings.py里的DEBUG变量就是主要的区别, DEBUG=True,说明是在开发环境(调试模式)下,DEBUG=False反之是在正式部署环境下使用。两者有很大的区别,比如缓存,出错信息的方式等等,还有今天说的静态文件的处理方式上。开发环境下静态文件都是通过Django自带的web服务器来处理的(这样会更方面)。如果把DEBUG设置成False,那么Django自带的web服务器自然不处理静态文件了,静态文件都交给nginx,apache来处理吧(这样会更高效)。具体说说static在开发环境下怎么配置吧。这次主要拿Django 1.4版本来做配置,这个要事先声明,因为1.4以后,Django的项目结构发生很大的变化,如果下面的配置做法放到Django 1.3上肯定不适应了,值得注意哦。staitc的配置只要在settings.py里做即可。DEBUG=True这个设定环境是处在开发环境下。然后自己建立一个变量SITE_ROOT,变量不是必须的,只是为了方面重用,名字可以随意起。import osSITE_ROOT=os.path.abspath(os.path.dirname(__file__))变量值项目的根目录,也就是settings.py的存放位置。然后给静态文件变量赋值,告诉Django,静态文件在哪里STATIC_ROOT = os.path.join(SITE_ROOT,'../static')说到这里,我还是说说项目文件结构吧,这个容易蒙人,比如这次的讲的项目结构如下:myproject----myproject--------__init__.py--------settings.py--------urls.py--------wsgi.py----blog--------__init__.py--------models.py--------views.py--------test.py----static--------css------------style.css--------js------------jquery.js--------images------------me.jpg----media--------upload注意项目的结构,你会发现SITE_ROOT就是myproject----myproject的路径。STATIC_ROOT就是myproject----media的路径。好,接着配置说STATIC_URL = '/static/'给静态文件url一个后缀,在templates里用到的。最后关键的部分是STATICFILES_DIRS以下配置STATICFILES_DIRS = ( ("css", os.path.join(STATIC_ROOT,'css')), ("js", os.path.join(STATIC_ROOT,'js')), ("images", os.path.join(STATIC_ROOT,'images')),)简要说一下,static文件夹在项目里,有css js images 三个文件夹(看项目结构),他们的路径分别是:os.path.join(STATIC_ROOT,'css'),os.path.join(STATIC_ROOT,'js'),os.path.join(STATIC_ROOT,'images');我们分别给他们起三个别名css,js,images(你可以随意给,不过为了易记,我们原名称指定别名了)到这里staitc算是配置完成了,并不需要再urls.py里配置相关的东西,Django就会自动找到对的路径解析静态文件了,也是在配置上static比media少了一步。配置好了,在templates 就能正常使用静态文件了。怎么用?拿一个templates讲解吧。<!DOCTYPE html><html lang="zh-CN"><head><meta charset=utf-8><title>staitc例子</title><link rel="stylesheet" type="text/css" href="{{STATIC_URL}}css/style.css" media="screen" /><script type="text/javascript" src="{{STATIC_URL}}js/jquery.js"></script></head><body> <img src="{{STATIC_URL}}images/me.jpg"" alt="img"></body></html>注意{{STATIC_URL}}就是取配置文件settings.py里的STATIC_URL变量,解析出来的就是:/static/。而{{STATIC_URL}}css/style.css最终解析出来的就是我们想要的:/static/css/style.css,Django会根据配置文件找到相应的文件。快到尾声的时候,讲讲正式部署环境怎么设置吧:DEBUG=False首先把DEBUG设置为False,告诉Django环境是正式的非调试模式下了,然后Django就不再通过自己来处理静态页面了,最后静态文件都交给Nginx Apache来处理了。说说Nginx怎么配置,才能正确解析静态文件吧,在一个server里添加一个location静态文件处理location /static/ { root /home/www-data/twogoo/myproject/; }这个也有一个容易犯错的地方,就是路径,有的同学常常指定这样的路径:/home/www-data/twogoo/myproject/staitc/;这样Nginx应该找不到静态文件的,因为Nginx会跑到/home/www-data/twogoo/myproject/staitc/staitc/路径里找,注意这点,静态文件处理上你会顺很多。(完了) -
改造Django的分页类
Django有个分页类Paginator,路径在django.core.paginator,我以前都是使用该类来对列表分页,在使用的过程中,产生了一些疑虑,比如以下代码就是分页用法的关键部分:page = int(request.GET.get("page",1)) blogs=Blog.objects.all() paginator = Paginator(blogs,10) page = paginator.page(page)分页的时候我总是取出全部的博客列表传到分页方法,如果数据量大的时候,性能可是打折扣了;有的人说,Django ORM有惰性缓存。但是回头想想,Django的惰性缓存是不错,这个可以有,但如果博客数据量达到一定数量级,Django第一次取数据的时候,问题依然存在的。有的人说,不要all,直接取想要的数据即可,嗯filter一下条件也好,少了n多的数据,但filter了某个条件后,数据量依然很大的时候,怎么办?似乎没有办法了。办法是有的,自己修改修改吧,所以今天决定拿Paginator类来修改了,我的想法是:分页方法里传入参数个数不变,但传入的记录列表是自己需要的条数,比如10条,15条...但Django的ORM规则这么摆着,想改出完美无暇的东西出来,真是费点周折,不然Django基金会早就改过来了,嗯,来个缺憾美吧,呵呵。我仔细读了Paginator源码,做了一下改动,代码如下。from math import ceil class InvalidPage(Exception): pass class PageNotAnInteger(InvalidPage): pass class EmptyPage(InvalidPage): pass class Paginator(object): def __init__(self, object_list, per_page, count=0, orphans=0, allow_empty_first_page=True): self.object_list = object_list self.per_page = int(per_page) self.orphans = int(orphans) self.allow_empty_first_page = allow_empty_first_page self._num_pages = None self.count=count def validate_number(self, number): try: number = int(number) except (TypeError, ValueError): raise PageNotAnInteger('That page number is not an integer') if number < 1: raise EmptyPage('That page number is less than 1') if number > self.num_pages: if number == 1 and self.allow_empty_first_page: pass else: raise EmptyPage('That page contains no results') return number def page(self, number): number = self.validate_number(number) return Page(self.object_list, number, self) def _get_num_pages(self): if self._num_pages is None: if self.count == 0 and not self.allow_empty_first_page: self._num_pages = 0 else: hits = max(1, self.count - self.orphans) self._num_pages = int(ceil(hits / float(self.per_page))) return self._num_pages num_pages = property(_get_num_pages) def _get_page_range(self): return range(1, self.num_pages + 1) page_range = property(_get_page_range) QuerySetPaginator = Paginator class Page(object): def __init__(self, object_list, number, paginator): self.object_list = object_list self.number = number self.paginator = paginator def __repr__(self): return '<Page %s of %s>' % (self.number, self.paginator.num_pages) def __len__(self): return self.paginator.count def __getitem__(self, index): return list(self.object_list)[index] def __iter__(self): i = 0 try: while True: v = self[i] … -
使用memcached作为Django的缓存
memcached不用介绍了,很出名的通用缓存中间件,Java,.Net,PHP,Python,Ruby等主流语言都能支持到。2goO网站之前一直用最原始的本地内存作为缓存,今天顺手改用memcached。过程很顺利,一两分钟就配好了,做下笔记:2goO现在用ubuntu系统,首先在系统安装memcached:sudo apt-get install memcached瞬间安装完毕,计划使用64M内存把它运行在11211端口下:memcached -d -m 64 -p 11211 -u root好了,memcached已经跑起来。最后就是在Django上使用它了,其中需要安装python-memcached作为桥梁,安装方法:pip install python-memcachedDjango settings配置文件里绑定刚才安装好的memcachedCACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', }}重启2goO,memcached正式被2goO项目所用。最后说说memcached服务的启动参数:-p 监听的端口-l 连接的IP地址, 默认是本机-d start 启动memcached服务-d restart 重起memcached服务-d stop|shutdown 关闭正在运行的memcached服务-d install 安装memcached服务-d uninstall 卸载memcached服务-u 以的身份运行 (仅在以root运行的时候有效)-m 最大内存使用,单位MB。默认64MB-M 内存耗尽时返回错误,而不是删除项-c 最大同时连接数,默认是1024-f 块大小增长因子,默认是1.25-n 最小分配空间,key+value+flags默认是48-h 显示帮助怎么查看进程能?netstat -anp|grep 11211查看11211端口端口可以看到它的进程:tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 28091/memcached tcp6 0 0 :::11211 :::* LISTEN 28091/memcached udp 0 0 0.0.0.0:11211 0.0.0.0:* 28091/memcached udp6 0 0 :::11211 :::* 28091/memcached可以用暴力的方法停止进程pid:kill -9 28091当然建议使用安全的方法操作:sudo memcached -d stop -u rootsudo memcached -d restart -u root(完) -
忆儿时
今天一直下雨,坐在靠背椅上看着窗外阴冷的天气,要不是因为小宝宝,我想我也没时间回忆小时候冬天的情形。 小时候家里挺穷的,是那种穷得叮当响的农村家庭,所以我们最怕过冬。因为冬天没钱买鞋子、袜子、厚衣服。所有这些都是捡亲戚的,他们有得给就是我们最开心的事情,哪怕是补了又补,满身都是补丁我们都乐意,毕竟不用挨冻了嘛!如果没有那冬天就惨了,穿着一双被冻得硬邦邦的烂拖鞋缩头缩脑的一步步挪去学校,全身发抖,鼻子通红,天气再冷一点鼻子吸气都是酸溜溜的。那时候我也挺懒上学的,冬天的很多时候都是我最后一个进教室,操场上一个人影也没有,都在教室里早读呢 。不过很庆幸我的学习成绩好,老师从来不追究我为什么迟到也不会罚站,就这样在冬天里我晃晃悠悠的度过了小学生活。 像那种阴冷又下雨的冬天,最期盼的是父母那天都不用去工作,然后给我们做好饭在家等着即将放学的我们,可惜这样的美事只能看着别人家发生。从我们懂事起,不管春夏秋冬从来都是姐弟几个分工合作把家务干完,顶多是下大雨的时候妈妈把菜从地里给我们摘回来。 夏天还好,随便一件破衬衫也能过,没鞋就赤脚上学,泥巴小道不会很炙热,但是夜里也是煎熬,大热天没有风扇就桑拿过一个晚上,即便有风扇也经常没电,想不起当初是怎么抗过来的了。三六九月是农忙,最苦是六月,收割完后马上又重新种上新稻谷,最怕赶雨,那种一会下雨一会放晴的天气可以把人的小命折腾掉,刚晒干的稻谷眼巴巴的看着湿透,特别有一种想毁灭的感觉。生在90年之前的农村人相信都经历过这样的事情,地里收割后因为长期下雨泡水熬烂的稻草没法耕地,必须一担担挑上岸那种情形,又重又臭,为了赶时间耕作,全家出动干活是必须的。我想家里耕地多劳动力少的估计为这个事情死的心都有。 放学恰逢下雨也是件恼人的事情,我们没有别人那么幸运下雨天有家里人送伞,除非村里来送伞的叔叔婶婶好心去家里给我们带上一把,或是刚好父母有事回家知道了拜托他们也给我们带上,不然我们就只能祈求有人施舍共享或是雨奇迹般的突然停了。当然在那个穷苦的年代我们成为落汤鸡的可能性比较大,一直到上了中学,那种盼望有人送伞、放学有人做好饭的生活念头才消失了。所以,特别希望快点长大,快点小学毕业,我们就可以奔向梦寐以求的初中。因为离学校远,我们上中学都要住校,虽然学校的大锅饭超级清汤寡水,记忆最深的是晚餐:春吃苦麦菜(偶尔还会在仅有的一瓢青菜里吃到臭虫),夏天空心菜,冬天大白菜,一般中午都是豆芽(初中毕业最恐惧提起的事情)。吃饭、洗澡都是争前恐后跑着去排队,艰苦但我们也乐此不彼了好长一段时间。 后来的生活貌似越来越好,我们也逐渐忘记了儿时想起来就哆嗦的穷苦日子,现在拼命的为每天的生活熬着。每个年代都有不同的辛酸,不过还是希望以后回忆起现在的时候能像现在回忆儿时一样会心的一笑,跟朋友家人聊儿时还有很多笑点,那N年之后我们回忆现在的自己还有没有更多的开心事呢? -
django impersonate app
Very useful django app to allow superusers to "impersonate" other non-superuser accounts. -
Speakerdeck Django Presentations
Speaker Deck is the best way to share presentations online, you can find lots django presentation resource higly recommended. some ... -
Lessons Learnt Building mongoengine
Recently, I attended both Pycon UK and Pycon Ireland to talk about the lessons I have learnt while maintaining mongoengine. -
cctv dome camera
We are one of the leading factories which develops and produces CCTV products in China, supported by the Chinese government ... -
Internationaliser ses programmes Python
Article qui aborde le sujet de la traduction d'un logiciel écrit dans le langage Python. -
OSQA is the free open source Q&A system
OSQA is the free, open source Q&A system.OSQA site is more than just an FAQ page, it is a full-featured ... -
Django Newbie Mistakes Wiki
official django Newbie mistakes wiki page aims to improve Django's error handling to catch such mistakes in the future. titles ... -
how to linux django deployment with nginx and gunicorn
how to on setting up Django on a Linux (Ubuntu) system using Nginx as a reverse proxy and Gunicorn as ... -
restore windows partition
Easy to download recover partition files application retrieve lost and formatted video file from deleted laptop hard disk. -
Randall Degges's blog
Randall Degges blog django posts you can find lot's of python posts as well some titles Django and SSL The ...