Tag Archives: django

11个你应该知道的django博客引擎【翻译】

这段时间一直在学python和django,准备写个小小的blog巩固下自己学到的东西,看到了GAE上的一些程序,大部分都是纯python的,想找一些基于django的,还真是难。无意中搜索到一篇文章,就翻译一下,渣技术,实在不行,就去看en文的吧。

en文地址

Michael Trier在两年以前就写了一篇叫“基于django的blog引擎在哪儿?”。James Bennett随后也跟着写了一篇名叫“哪儿才有django的blog应用”,他论述了为什么最终没有Django blog engine(也就是基于django的博客引擎)。最近Daniel Greenfeld写了一篇“向哥展示你们的开源Django blog吧”,它里面,他定义了这个Django blog项目所需要的各项要求。自从读了那篇文章以后,我就开始一直写现在的这篇文章。

下面我挑选了一些我相信你应该会注意的blog引擎,并且根据它们最近的更新日期排列。如果这些blog engine的作者描述了他们的blog,那么我就直接引用作者们的描述,如果没有,那哥就总结一下我对该项目的一些了解。如果你有自己开发的blog引擎并且值得哥注意的,那么就在下面留言吧,记得加上姓名和地址。

Byteflow博客程序并没有被包含在下面,这是因为这个项目在我写这片博客之前就已经关闭了下载的地址(= =!)。

Biblion

标语:eldarion.com 的blog程序一般适用于企业或者项目级别的引用。

源码地址:http://github.com/eldarion/biblion

最后更新:2010年2月9号

在线的demo:http://eldarion.com/blog/

描述:Bilion是eldarion.com的一个已经被提取和开源的blog程序,这个blog目前的定位是,它能够被应用于类似的eldarion.com和pinaxproject.com这样的网站或者博客项目。一旦我们完成Bilion的功能,那么我们就用它去代替内部的Pinax博客程序。

特点:

1.多渠道支持(比如:技术对业务)      #这句真没看懂啥意思

2.使用Creole作为标记格式

3.Atom feeds            #求翻译帝现身

4.在博客发布前预览其效果

5.可以选择同步推特

Django-article

标语:牛X的基于django开发的博客引擎

源码:http://bitbucket.org/codekoala/django-articles/

最后更新:2010年2月8号

现在demo:codekoala.com

描述:作者是Josh VanderLinden,牛X的基于django开发的博客引擎。

显著特点:

1.标签系统

2.在django的后台中自动完成标签功能

3.支持草稿(就是现预存,以后再发布)

4.文章到期设定     #这是啥设定啊,还翻译有毛病

5.可以使用文本或者HTML或者使用Markdown或者ReStructured Text或者Textile markup来写文章。                  #这里面有几个属于不是很懂

6.支持相关文章显示

7.支持后续文章(就是上一篇下一篇)

8.支持Disqus评论系统               #想知道Disqus是啥,请猛击。

9.文章分页存档

10.支持多语言(国际化个锤子)

11.支持为每篇文章添加个单独的链接,并且检测该链接。  #连wordpress的url设定差不多。- -,我猜的。

12.字数统计             #这个功能到底有个啥锤子用啊

13.支持最新文章的RRS Feeds

14.支持最新的文章标签的RRS Feeds

娘的,真累,而且翻译得不好,以后有时间再翻译翻译吧,真蛋疼。

django中Admin的一些细节

django中有一个叫admin的管理界面,可以和简单的配置和使用,用来完成一些CURD工作。

这段时间正好想通过写个基于django的blog,从中把知道的东西系统化。

这与怎么安装,如果在django中添加自己的模块就不说了。直接记录自己不是非常熟悉的一些问题。

1.设置字段可选

这个问题就是看你是怎么建表的,前面说过,djanog可以直接通过模型建表,而通过django简称的表呢,每个字段的默认值都是为NOT NULL的,而自己建表的话,一般都是为NULL。

在mysql中,NULL表示未知的,非法的,一般用来指定空值。

一般我们要指定某个字段是可选的话,在模型中,指定参数为”black=True”就可以了。

在编写模块的时候,一般就指定了字段的类型以及长度。我们也可以设置日期型字段和数字型字段的可选。同样是通过设置参数blank=True就可以。但是一般要加上一个NULL=True,但是它并没有改变数据库,django一般是不会修改已经生成的表的。

自定义字段的标签

因为django的admin直接使用了字段名称作为表单的名称,如果想弄成中文的话,那么在字段的参数里面设置verbose=”就好。如果设置成中文,别忘记设置文件的编码。

以上的修改都是模块级别的修改,修改的模块的组成部分,而这部分是管理工具所能用的。

自定义ModelAdmin类

1.自定义列表

这是针对管理工具的配置。可以通过自定义模型中的__unicode__函数,返回要列出的字段。

2.自定义表单

通过定义一个ModelAdmin类,通过指定fields的属性值(一个元组)实现对表单先后排列。

django的安全问题

这篇东西写完了以后,就准备写个留言板,熟悉python以及django。让后再写个blog,当然了功能不可能写得很多,纯粹给自己练练手,让后再开发个企业网站啥的,研究下常用的功能以后,就插入了了解python。

在django book上面的内容了解得差不多了,然后还有一些应用可能目前还没办法用到,所以想想等以后用到的时候再回来看看,包括国际化啊,子框架,中间件这些,准备先了解个概念,等以后用到再研究。

还是现说这一章的安全问题吧,这个地方也是我的一个薄弱点。

1.任何从客户端传递过来的数据都应该经过检查,无论是用户数据(表单)还是带外数据(HTTP头,cookie之类的)。

2.SQL注入

SQL诸如就是改变网页的参数,加入一些SQL片段,让后让网站直接运行,从而得到他想要的数据,或者直接删除了。

解决方案:那就是转义了,django默认是对接受到的SQL进行转义的。但是如果想接受原始的SQL语句的话,可以使用extra()函数。

3.XSS(跨站点脚本攻击)

XSS就是在页面被渲染成HTML页面之前,向网页中插入一些<script>标签形式的HTML代码。一般就是为了获得用户的cookie信息或者session信息。也不知道为什么要劫持页面,可能是蛋疼吧。他插入的HTML集可能是个钓鱼的表单,骗你输入一些敏感内容。

解决方案:首先,我应该很明白,任何用户输入的内容都是应该进行转义的。为了防止被XSS,django会转义所有的变量值。

4.伪造跨站点请求

CSRF就是一些蛋疼的web站点利用正常的用户去下载某个站点的URL时候,这个站点已经通过信任验证,所以攻击者就利用这种被信任的状态做些OOXX的事情。

解决方案:django有内建的工具来解决。

5.会话(cookie和session)

会话的攻击方式很多,比如伪造cookie,伪造session,会话中毒啊,诱骗用户充值sessionID,方式很多,而且都是在cookie和session上做手脚。

解决方法:不要在URL中包含session信息,这个是很安全的,而且django也不容许URL中包含session。不要在cookie中保留数据,只保留一个ID就行了,毕竟cookie是存储在客户端的。如果要在模板中显示session,那么请转义。

6.debug信息被暴露

很多时候,在开发站点的时候,我们都是开启了debug模式,因为它能高速我错误的情况。但是有时候上线了,却仍旧开启了debug模式。

解决方案:在settings.py中设置debug为false,如果使用了mod_python,那么还需要在apache的配置文件里面设置PythonDebug Off。

总的来说,就是不要相信用户数据,包括表单也好,啥也好。同时也不要相信URL的参数,因为它们是可变的。对文件和文件夹的权限设置要做得很好。

django处理用户以及权限认证

其实我不是灰常喜欢django的这种打包模式,啥都给我们做好了,我们以后还干啥,不过有时候为了偷懒到可以做做也不错。

在django的内部有一个auth/auth的系统,也就是认证与授权,说得再土点,就是用户的登录验证,以及用户的权限分配。

打开django的认证支持。

就跟cookie一样,认证支持也是一个django应用,放在django.contrib中,需要安装,但是默认下已经安装了。安装这个之前必须安装session框架,不让是工作不了的。

安装好了后应该运行manage.py syncdb来创建对应的数据库。

安装好了以后,就可以处理用户了(处理用户 – -),request.user这个对象表示当前已经登录的用户。可以通过is_authenticated()来判断用户是否已经登录了。

例如:

if request.user.is_authenticated():

#可以等已经登录的用户操作

else:

#可以对没有登录的用户操作

深入插入User对象

User实例一般从request.user中获得。它包含了很多的属性和方法用来操作。而对于没有登录的用户(AnonymousUser对象)只是模拟了其部分的部分的接口。

登录和退出

django给出了两个函数用来处理用户的登录和推出,一个是authenticate(),它接受两个参数,一个是用户的username,一个是用户的password,如果用户名和密码都合法,则返回一个User对象,否则返回None。但是这个函数并不是登录,它只是验证一个用户的证书而已。要登录,使用login()。

login有两个参数,一个是HttpResquest对象,一个User对象。

用户退出可以使用django.contrib.auth.logout(),它接受一个HttpResquest对象,没有返回值。

其实我们偷懒的话,可以不需要写这些函数,因为django的auth/auth系统已经提供了内置的对应函数。

直接在URLconf中定义login()和logout()就OK。

用户限制

可以使用is_authenticated()来检查用户是否已经登录,当然啦,更快更懒的方式是使用login_required修饰符。

from django.contrib.auth.decorators import login_required

@login_required

def test(request):

pass

好了,还有些东西,以后实际操作的时候再补上。

django处理cookies和session

cookie和session是个啥,鬼畜都知道,所以不说鸟。直接开记录在djano框架下面如何操作cookie和session。

存取cookies

读取cookies很简单,因为读取cookies可以使用HttpResquest,每一个HttpResquest对象都有一个COOKIES对象,可以用它读取任何浏览器发送给视图的cookies。

因为每个视图函数的第一个参数都是request,其实它就是一个HtppResquest对象,所以直接使用request.COOKIES读取cookies就好。

写COOKIES就使用HttpResquest对象的set_cookie()方法,set_cookie有一些可选参数来指定一些特殊操作。

session操作

开启session(他是通过一个中间件和一个模型来实现的)。

1.编辑MIDDLEWARE_CLASSES,确保里面已经包含了django.contrib.sessions.middleware.SessionMiddleware。

2.确认INSTALLED_APPS,确保里面已经含有一个叫django.contrib.sessions的鬼畜。

其实这两项,一般默认就有了,前提是你的项目是用python manage.py startproject mysite来创建的。

视图中使用session

SessionMiddleware被激活以后,每个视图函数的第一个参数request(也就是HttpResquest对象)都有一个session属性,它和cookie一样,也是个字典型的对象,可以像使用普通字典那样使用。

在操作session时候的一些忌讳:

1.使用正常的的字符串来访问字典,而不是整数,对象,或者其他什么很讨厌的东西。

2.key值最好不要使用下划线来命名,因为有些是保留的,但是一般也用不到。

3.不要用一个新对象来替代request.session。

4.不要向request.session中存属性。

测试COOKIE

当然鸟,有些贱人就是喜欢关闭cookie,所以作为蛋疼的web开发者们,想在人家机器上存储一个cookie都得先test一下。

可以使用request.session.set_test_cookie()来测试,让后在其他的视图中使用request.session.test_cookie_worked(),两次测试是不在同一个视图函数中的,为什么要这样,跟cookie的工作原理有关。

delete_test_cookie可以用来删除用于测试而设置的cookie。

在视图之外使用session

我们可以使用django的数据库API来存取session,我们使用get_decoded来读取实际的session数据。

有效期

如果SESSION_EXPIRE_AT_BROWSER_CLOSE设置为false,那么cookie在浏览器中保存周期是SESSION_COOKIE_AGE秒。如果设置为true,那么关闭浏览器时候,就会失效。

在apache上部署django

好吧,继续每天不更新不舒服斯基,不折腾就会死星人。

早上花了以一上午的时间,在apache上成功的部署了django,虽然还有写地方不明白,但是记录一下又不会怀孕,顺便加强印象。

好吧,至于django如何安装,apache如何安装,python如何安装就不废话了,直接记录。

首先是配置好apache的开发目录,我选的是D:/py,让后python django-admin.py startproject mysite,开始一个项目,然后在D:/py下建立一个mysite的文件夹,复制,copy。

然后优势配置apache了。这次的配置稍微有点麻烦。首先:

<Location “/”>
SetHandler python-program
PythonPath “['D:/py'] + sys.path”
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonDebug Off
</Location>
需要指明的是,D:/py是你项目的上一级目录,而mysite.settings是你project的名称。
PythonDebug Off是关闭调试模式,ON就是开启,如果产品上线了,一定要Off的。
MaxRequestsPerChild 1,这一句不是加载Location里面,放在其他的什么地方都可以,因为在开发的时候,不是php,每次更改代码后,直接刷新页面就好。python是不行的,他需要重启apache,很蛋疼,加入MaxRequestsPerChild 1后会好点,它会在发送请求时候重新载入所有代码,但是它并不是重启,所以有时候,你需要等一小段时间。
然后基本上就没问题了。当然了,因为具体情况的不同,会碰到很多蛋疼的问题,最常见的就是无法找到settings,其实这里主要是PythonPath “['D:/py'] + sys.path”没有填写正确,也就是没有加路径。有时候,你还需要指定Django在python中的路径以及project的路径。但是具体什么情况下,我也不懂,所以我直接都加上了。
还有就是目录无法访问,因为一般默认情况下是无权限的,因为python代码的部署和php是不同的,python代码不放在根目录。所以需要指定媒体文件的权限。
<Directory “D:/py/mysite/media/”>
Order deny,allow
Deny from all
</Directory>
指定好路径就OK了。
参考地址:
http://hideto.javaeye.com/blog/43252
http://www.javaeye.com/topic/168933
http://linux.chinaunix.net/techdoc/install/2009/06/25/1120348.shtml
http://djangobook.py3k.cn/2.0/chapter12/

插入了解django的模板知识

RequestContext和Context处理器:

两者都是用来渲染模板的,不同的是RequestContext默认的地在模板中加入了一些变量,比如HttpRequest对象或者当前登录用户的信息,一般情况下,如果你在很多模板中有使用相同的变量,使用RequestContext会好点。

如果要使用render_to_response()这种简写方式,就需要使用context_instance这个参数了。

RequestContext有两个参数,第一个就是HttpResquest对象,一般是request。另一个是包含了Context处理器的列表或者元组。一般可以用来传递先前定义的处理器函数。

用法如下:

def ob_proc(request):

return {

‘ip’:request.META[REMOET_ADDR],

…….

}

context_instance = RequestContext(request, processors=[ob_proc])

如果数据多了,模板也多了,还是得不停的写processors,其实我们可以指定一些默认的processors。django提供了对全局的context处理器的支持。settings.py中添加TEMPLATE_CONTEXT_PROCESSORS来指定了默认的context processors。

html自动转意:

在django默认的情况下, 每一个模板都会自动的转意每一个变量标签的输出。包括一些特定符号,比如:” > “,” ‘ “, ” ” “, ” & “。

我们在不需要使用的时候也可以关闭这个默认的过滤,比如对于一个单独的变量,我们可以使用safa来关闭转意。比如:

my name is {{ name |safe}}

对于模板块,可以使用autoescape来进行关闭自动转意,比如:

{% autoescape off %}

Hello {{ name }}

{% endautoescape %}

而且autoescape有on和off两个参数,off显然就是关闭自动转意,但是在off包含的内容里面,如果要开启,就必须使用on参数了。

过滤器参数里的字符串常量的自动转义:

过滤器其实也可以是个字符串,而且可以直接使用,因为他们已经在被编写的时候就保证了安全性和正确性。

模板的加载:

有两种方法可以加载模板,一种是使用get_template(template_name),这种是直接返回已经被编译过的模板,如果不存在,就报错思密达。还有一种是用select_template(template_name_list),它使用一个模板名称的列表作为参数,返回列表中存在的第一个参数。如果模板都不存在,报错思密达。

好了,更多的,下次在记录

django的URL和视图配置,插入版(二)

在python中,函数的参数有两种形式,一种是关键字参数,一种是位置参数。要说一下的是,关键字参数。

比如:

def Hello(var=’hello world’):

print var

还是比较好理解,这样的话,python就不会在意参数的位置。而且关键字参数和位置参数也是可以混合使用的。这种情况下,所有的位置参数都必须在关键字参数的前面。

说过了,django的URL配置其实使用的就是python的正则表达式规则。而匹配的规则里面也有无名组和命名组(语法是(?P<name>pattern),其中name是组的名字,而pattern就是规则了)。

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
    (r'^articles/(?P<year>\d{4})/$', views.year_archive),
    (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', views.month_archive),
)
比如这个代码,输入到视图函数里面就是
year_archive(year='')
还是很好解释的。
传递额外的参数到视图函数中:
URLCONF配置里面的元组的第三个参数是个字典,它可以指定额外的参数。
这些玩意还是得联系才能琢磨,等下去写点儿代码试验一下。

视图和URL配置的插入了解(一)

前面的看来是很简单的,其实想想也知道,要一个视图函数一个视图函数的导入,然后配置URLconf,那还不蛋疼到暴啊。

from django.conf.urls.defaults import *
from var.views import contact_form, contact, meta
urlpatterns = patterns(”,
# Uncomment the next line to enable the admin:
(r’^contact-form/$’, contact_form),
(r’^contact/$’, contact),
(r’^meta/$’, meta),
)
那么显然,我要配置views里面视图函数的URL,我得不停的导入视图函数。一个几个还好,还是大项目,那还不蛋疼到暴。而且也很不容易区分啊。
所以简单点的写法是
from django.conf.urls.defaults import *
from var import views
urlpatterns = patterns(”,
# Uncomment the next line to enable the admin:
(r’^contact-form/$’, views.contact_form),
(r’^contact/$’, views.contact),
(r’^meta/$’, views.meta),
)

这样就简单点了。其实还可以简单点,但是也说不上简单,但是可以写得跟明白点儿。

from django.conf.urls.defaults import *
urlpatterns = patterns(”,
# Uncomment the next line to enable the admin:
(r’^contact-form/$’, ‘var.views.contact_form’),
(r’^contact/$’, ‘var.views.contact’),
(r’^meta/$’, ‘var.views.meta’),
)
这种写法个人感觉比较好,而且容易明白,但是要注意的是,前两种写法是不需要单引号的,而第三种写法需要写单引号,否则报错思密达。
当然了,再精简一点就更好了,谁也不想老写var.views,那么就把它作为一个前缀好了,而urlpatterns的第一个一直为空的那个参数,其实就是指定前缀的。
from django.conf.urls.defaults import *
urlpatterns = patterns(‘var.views’,
# Uncomment the next line to enable the admin:
(r’^contact-form/$’, ‘contact_form’),
(r’^contact/$’, ‘contact’),
(r’^meta/$’, ‘meta’),
)
这样写,应该就更好了,注意的是,单引号还是不能去掉。
那就有鬼畜问了,如果有多个前缀,那他娘的咋办啊。其实也很好办,比如我们现保留上面那坨代码,然后加上:
urlpatterns += patterns(‘pro.display’,
(r’^show/$’, ‘show’),
)
这样的话,因为+=是链接两个变频,所以,就相当于合并了这个二元的元组。urlpatterns 是唯一的,是django在初始化时候要寻找的,所以不要另外再命名一个,不然报错思密达。urlpatterns ()返回的对象是可以相加的。
好了,现这么多,明天继续。

django表单的处理

这几天都没更新,有两次写到一般就直接不写了,囧 = =!,好吧,继续更新,根据自己的学习进度,今天应该是记录一些django在处理表单方面的特点。其实表单而已,传递方式不是post就是get,但是django为了让更偷懒,还额外加了一个Form类。

1.从request对象中获取数据

在视图函数中,每个函数的第一个参数都是request,其实他们都是HttpRequest对象。而这个名为request的HttpRequest对象则包含了一系列的URL信息,有点类似于php中的$_SERVER。

URL的信息灰常多,列举几个常用的。

request.path,除了主域名以外的请求路径。

request.get_full_path,这个根据名字就看出了,是除了主域名以外的的路径。包括参数信息。

request.get_host,获取主机,要么是IP地址,要么是域名。

还有一个是request.META,他是一个字典(其实我想说它是个关联数组,但是貌似python里面都是说列表),包含了本次HTTP请求的Header信息。

比如,用户的IP,可以是REMOTE_ADDR。

浏览器的user_agent字段,可以用HTTP_USER_AGENT获得。

这里要注意的因为它是个普通的字段,所以如果访问不存在的键值时候,是会爆出keyerror错误的(因为Header信息是根据用户发送的信息和服务器设置的信息决定)。所以使用的时候,多使用try-except吧。其实个字典包含的信息还是很多,可以递归查看。

接受数据

POST与GET区别:POST一般用户处理接受到的表单,而GET是用于显示的,也就是说POST过来的数据一般都要进行数据库的操作的,而GET只会提取,而不会有其他操作。

GET:用request.GET['ob'],这个一般可以接受带问号的url后面所接的参数,比如/show/?id=2,那么request.GET['id']就是等于2.

POST:可以用request.POST(‘ob’)来获取。如果要判断接受到的数据是否为空,或者其他操作,可以使用request.POST.get(‘ob’, ‘action’)来操作。

这里有个地方还是很蛋疼的。就是使用GET提交数据的时候呢,会很正常,但是如果使用POST呢,就会报错。我一开始还以为是自己代码问题,后来一看是个403,而且有很好的提示,SO,google之,原来要在MIDDLEWARE_CLASSES里面加上一条django.middleware.csrf.CsrfResponseMiddleware,这样一来就不会报错了,而且数据也能接受到。

Form类

这个哥们呢,会为每个要处理的表单建立一个form类。表单中的每个字段作为Form类的一个属性,比如我们现在有一个表单,有两个域。分别是usenname,email。那么我们在书写的时候就是:

from django import forms

class EmailForm(forms.Form):

username = forms.CharField()

email = forms.EmailField(required=False)

这个,有点儿类似于模块的书写。都能指定类型,都是作为一个单独类的属性。都可以指定能否为空(required=False)。

其实Form类的出现,一方面是简化了表单的操作,另一方面也减少了代码的书写量,以为一个form =ExampleForm(request.POST)就能或者一个为字典的值,里面包含了对应的值。

好了,更深入了了解还是得去多写代码才能体会。