ADMIN_MEDIA_PREFIX = '/admin_media/'
(r'^media/(?P
.*)$', 'django.views.static.serve', {'document_root': '/Users/username/django/django_projects/project_name/media'}), MEDIA_ROOT = '/Users/username/django/django_projects/project_name/media/'
MEDIA_URL = '/media/'
Wednesday, June 27, 2007
setting.py & urls.py for /media/
Monday, June 25, 2007
常用开源协议详细解析
开源在今天的软件业已经很普遍,但开源是否意味着使用者可以对开源后的代码为所欲为呢?答案是否定的.开源运动同样有自己的游戏规则和道德准则.不遵行这些规则不但损害开源运动的健康发展,也会对违规者造成名誉和市场上的损失,更可能陷入法律纠纷和赔偿.
首先,要对几个概念有所了解:
1. Contributors 和 Recipients
Contributors 指的是对某个开源软件或项目提供了代码(包括最初的或者修改过的)发布的人或者实体(团队、公司、组织等),Contributors 按照参与某个软件开源的时间先后,可以分为 an initial Contributor 和 subsequent Contributors .
Recipients指的是开源软件或项目的获取者,显然,subsequent Contributors 也属于 Recipients之列.
2. Source Code 和 Object Code
Source Code 指的是各种语言写成的源代码,通过Source Code,结合文档, 可以了解到整个软件的体系结构及具体到某个功能函数的实现方法等.
Object Code 指的是Source Code 经过编译之后,生成的类似于“类库”一样的,提供各种接口供他人使用的目标码,按我的理解,它就是像常见的DLL、ActiveX、OCX控件性质的东西.(不知道这样理解对不对)
分清楚这两个概念的目的在于,有些开源,只发布Object Code ,当然,大多数发布的是Source Code.很多协议也对 “你发布的是哪种Code的时候应该怎样”,有着明确的约束.
3. Derivative Module 和 Separate Module
Derivative Module 指的是,依托或包含“最初的”或者“从别人处获取的”开源代码而产生的代码,是原“源代码”的增强(不等于增加)、改善和延续的模块,意为“衍生模块”.
Separate Module 指的是,参考或借助原“源代码”,开发出的独立的,不包含、不依赖于原“源代码模块”,意为“独立的模块”.理解这两个概念的目的在于,很多协议对涉及到商业发布的时候,会有哪些是衍生的,哪些是独立的,有着明确的商业发布规定.
现今存在的开源协议很多,而经过Open Source Initiative组织通过批准的开源协议目前有58种.我们在常见的开源协议如BSD, GPL, LGPL,MIT等都是OSI批准的协议.如果要开源自己的代码,最好也是选择这些被批准的开源协议.
这里我们来看四种最常用的开源协议及它们的适用范围,供那些准备开源或者使用开源产品的开发人员/厂家参考.
BSD开源协议(Berkeley Software Distribution )
BSD开源协议是一个给予使用者很大自由的协议.基本上使用者可以“为所欲为”可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件 再发布.但“为所欲为”的前提当你发布使用了BSD协议的代码,或则以BSD协议代码为基础做二次开发自己的产品时,需要满足三个条件:
1. 如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议.
2. 如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议.
3. 不可以用开源代码的作者/机构名字和原来产品的名字做市场推广.
其实这几个规则约定的目的也只是达到一个目的:是他人的东西,别人以BSD开源了,你就不能不做任何声明而占为己有,更不能用他人的名义来做商业推广.你只对你自己的东西拥有绝对控制权.
举个例子,你用开源代码(A)修改或做其他增添之后,产生了产品B,这时候,你对B的控制由你自己决定,你可以用任何协议再开源,也可以闭源商业发布. 但,因为如果B中包含了A或A的一部分(一点都不包含就不叫修改了),那你在B产品的版权声明中,必须有提到你有使用到 A ,并且附带上 A 的开源协议.而且不能做商业推广的时候将B 冠以原开源作者的名义以促进商业推广.
BSD代码鼓励代码共享,但需要尊重代码作者的著作权.BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上
开发商业软件发布和销售,因此是对商业集成很友好的协议.而很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发.
Apache Licence 2.0
Apache Licence是著名的非盈利开源组织Apache采用的协议.该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布(作为开源或商业软件).需要满足的条件也和BSD类似:
1. 需要给代码的用户一份Apache Licence
2. 如果你修改了代码,需要再被修改的文件中说明.
3. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明.
4. 如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence.你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改.
Apache Licence也是对商业应用友好的许可.使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售.
GPL (Gun General Public License)vesion 2.0 1991
我们很熟悉的Linux就是采用了GPL.GPL协议和BSD, Apache Licence等鼓励代码重用的许可很不一样.GPL的出发点是代码的开源/免费使用和引用/修改/衍生代码的开源/免费使用,但不允许修改后和衍生的代 码做为闭源的商业软件发布和销售.这也就是为什么我们能用免费的各种linux,包括商业公司的linux和linux上各种各样的由个人,组织,以及商 业软件公司开发的免费软件了.
GPL协议的主要内容是只要在一个软件中使用(“使用”指类库引用,修改后的代码或者衍生代码)GPL 协议的产品,则该软件产品必须也采用 GPL协议,既必须也是开源和免费.这就是所谓的“传染性”.GPL协议的产品作为一个单独的产品使用没有任何问题,还可以享受免费的优势.
由于GPL严格要求使用了GPL类库的软件产品必须使用GPL协议,对于使用GPL协议的开源代码,商业软件或者对代码有保密要求的部门就不适合集成/采用作为类库和二次开发的基础.
最常见的开源协议,使用它作为授权协议的有大名鼎鼎的 Linux .GPL最显著的两个特点就是网上称为的“病毒性传播”和“不允许闭源的商业发布”.
所谓的“病毒性传播”,指的是,GPL规定,所有从GPL协议授权的源码衍生出来的(即上面提到的Derivative Module),或者要跟GPL授权的源码混着用的Project,都要遵循GPL协议,就像病毒一样,粘上了关系,就“中毒”了.GPL这样规定的目的 是,保证在GPL协议保护下的产品,不会再受到其他协议或者授权的约束.即让跟GPL有关系的源码都能免费获取.举个例子,如果你的改进的Linux中使 用了GPL授权下的开源模块(也必须使用,你不可能自己重新去做个内核吧,如果做出来了,你也没必要叫Linux了.),那么你整个Linux产品也必须 遵循GPL协议去开源,不能以其他方式去开源发布,更不允许闭源发布.这样一来,就不会出现这样一个Linux--这个功能是GPL协议授权的,可以免费 获取源码,而另外一个功能是其他协议下的,拿不到源码.这点规定对使用或者研究该产品的人来说,是一个极大的便利.
而“不允许闭源商 业发布”指的是,在GPL授权下,你的软件产品可以商业发布,拿去卖钱,但是在这同时,你也必须将该产品的源码以GPL协议方式开源发布出去,供他人免费 获取.也许有人会迷惑,拿去卖,又同时开源,那谁来买阿?这个产品怎么赚钱呢??这就涉及到开源产品的商业模式的问题了,想了解相关一些信息的话,可以看 看以上我给出链接的一些文章.至于后面,可能会写一篇关于开源项目的商业模式的随笔.
GPL协议下的商业发布的一个关键点就像 Java 视线论坛的 Robbin所说的,GPL是针对软件源代码的版权,而不是针对软件编译后二进制版本的版权.你有权免费获得软件的源代码,但是你没有权力免费获得软件的 二进制发行版本.GP对软件发行版本唯一的限制就是:你的发行版本必须把完整的源代码一同提供.
它细节如再发布的时候需要伴随GPL协议等和BSD/Apache等类似.
LGPL
LGPL是GPL的一个为主要为类库使用设计的开源协议.和GPL要求任何使用/修改/衍生之GPL类库的的软件必须采用GPL协议不同. LGPL允许商业软件通过类库引用(link)方式使用LGPL类库而不需要开源商业软件的代码.这使得采用LGPL协议的开源代码可以被商业软件作为类 库引用并发布和销售.
但是如果修改LGPL协议的代码或者衍生,则所有修改的代码,涉及修改部分的额外代码和衍生的代码都必须采用 LGPL协议.因此LGPL协议的开源代码很适合作为第三方类库被商业软件引用,但不适合希望以LGPL协议代码为基础,通过修改和衍生的方式做二次开发 的商业软件采用.
GPL/LGPL都保障原作者的知识产权,避免有人利用开源代码复制并开发类似的产品.
CPL(Common Public Liecense) vesion 1.0
CPL是IBM 提出的并通过了OSI(Open Source Initiative)批准的开源协议.主要用于一些IBM或跟IBM相关的开源软件/项目中.如很著名的Java开发环境 Eclipse 、RIA开发平台Open Laszlo等.
CPL也是一项对商业应用友好的协议.它允许 Recipients 对源码进行任意的使用、复制、分发、传播、展示、修改以及改后做闭源的二次商业发布,这点跟 BSD 很类似,也属于自由度比较高的开源协议.但是,需要遵循:
1. 当一个Contributors将源码的整体或部分再次开源发布的时候,必须继续遵循 CPL开源协议来发布,而不能改用其他协议发布.除非你得到了原“源码”Owner 的授权.
2. CPL协议下,你可以将源码不做任何修改来商业发布.但如果你要将修改后的源码其开源,而且当你再发布的是Object Code的时候,你必须声明它的Source Code 是可以获取的,而且要告知获取方法.
3. 当你需要将CPL下的源码作为一部分跟其他私有的源码混和着成为一个 Project 发布的时候,你可以将整个Project/Product 以私人的协议发布,但要声明哪一部分代码是CPL下的,而且声明那部分代码继续遵循CPL.
4. 独立的模块(Separate Module),不需要开源.
Yesky编译
Sunday, June 24, 2007
Disable System Beep
# turn off the PC speaker
blacklist pcspkr
Add the following to /etc/rc.local:
for i in 1 2 3 4 5 6
do
setterm -blength 0 > /dev/tty$i
done
vi /etc/rc.local
add this line to the end of your script
just before the exit 0
restart service or computer.
modprobe -r pcspkr
exit 0
Or
Put this command in /etc/profile:
setterm -bfreq 0
svn propset
svn propset svn:keywords "Id" V2EXCore.php
Subversion 中可以使用的 Keyword 包括下面这些。
- Id
这是一种综合的格式,例如“$Id: V2EXCore.php 4 2005-10-29 23:08:09Z livid $”。- LastChangedDate
最后被修改的时间,这个属性也可以缩写为 Date。- LastChangedBy
最后修改该源代码文件的用户名,这个属性也可以被缩写为 Author。- LastChangedRevision
最后修订的版本号,这个属性也可以被缩写为 Revision 或者 Rev。- HeadURL
该源代码文件所位于的 Repository 上的绝对 URL 地址,这个属性也可以被缩写为 URL。
Subversion 只会对你明确设置了 Keyword 进行更新,比如如果你对某个源代码文件执行了下面这条指令。svn propset svn:keywords "Id Date" V2EXCore.php
则在 V2EXCore.php 中所有的 $Id$ 和 $Date$ 都会被替换,而 $Author$ 之类的没有被设置的属性则不会发生替换。
Wednesday, June 20, 2007
Testing Django applications
Doctest
For example:
from django.db import model
class Animal(models.Model):
"""
An animal that knows how to make noise
# Create some animals
>>> lion = Animal.objects.create(name="lion", sound="roar")
>>> cat = Animal.objects.create(name="cat", sound="meow")
# Make 'em speak
>>> lion.speak()
'The lion says "roar"'
>>> cat.speak()
'The cat says "meow"'
"""
name = models.CharField(maxlength=20)
sound = models.CharField(maxlength=20)
def speak(self):
return 'The %s says "%s"' % (self.name, self.sound)
When you run your tests, the test utility will find this docstring, notice that portions of it look like an interactive Python session, and execute those lines while checking that the results match.
For more details about how doctest works, see the standard library documentation for doctest
unittests
Like doctests, Django’s unit tests use a standard library module: unittest. As with doctests, Django’s test runner looks for any unit test cases defined in models.py, or in a tests.py file stored in the application directory.
An equivalent unittest test case for the above example would look like:
import unittest
from myapp.models import Animal
class AnimalTestCase(unittest.TestCase):
def setUp(self):
self.lion = Animal.objects.create(name="lion", sound="roar")
self.cat = Animal.objects.create(name="cat", sound="meow")
def testSpeaking(self):
self.assertEquals(self.lion.speak(), 'The lion says "roar"')
self.assertEquals(self.cat.speak(), 'The cat says "meow"')
When you run your tests, the test utility will find all the test cases (that is, subclasses of unittest.TestCase) in models.py and tests.py, automatically build a test suite out of those test cases, and run that suite.
For more details about unittest, see the standard library unittest documentation.
Testing Tools
To assist in testing various features of your application, Django provides tools that can be used to establish tests and test conditions.
Running tests
Run your tests using your project’s manage.py utility:
$ ./manage.py test
If you only want to run tests for a particular application, add the application name to the command line. For example, if your INSTALLED_APPS contains myproject.polls and myproject.animals, but you only want to run the animals unit tests, run:
$ ./manage.py test animals
When you run your tests, you’ll see a bunch of text flow by as the test database is created and models are initialized. This test database is created from scratch every time you run your tests.
Tuesday, June 19, 2007
Python Inner Classes
class Outer:
def __init__(self):
self.x = 5
class Inner:
def __init__(self):
self.y = 10
if __name__ == '__main__':
outer = Outer()
inner = outer.Inner()
print outer.x
print inner.y
print inner.x
I've been seeing a pattern where I'd like to be able to create nested class hiearchies like this. Usually it's due to containment. For example, let's say I have a Tools class that can hold a bunch of tool classes like Hammer or Sawsall. Now, I'd like my tool classes to be able to get back at their containing Tools instance. I generally model these classes like this:
class Tools:
def __init__(self):
self.tools = []
def add(tool):
self.tools.append(tool)
class Hammer:
def __init__(self, tools):
self.tools = tools
class Sawsall:
def __init__(self, tools):
self.tools = tools
Okay, so you can see the pattern, right? Each tool class is going to have this tools argument that tells them who their container is. But this doesn't seem right to me. That the tool classes need reference to their container shouldn't have to bother the person using these classes. It seems a bit weird that I would create an Sawsall instance passing a reference to the container I plan to add it to.
tools = Tools()
sawsall = Sawsall(tools)
tools.add(sawsall)
It just looks redundant. Here's how I would like that to read:
tools = Tools
sawsall = tools.Hammer()
tools.add(sawsall)
Now, that's still a little redundant and doesn't seem entirely correct for some reason but I think the container.Class() convention is more clear than the other way. Even without inner classes, we can still get this functionality by adding a Hammer() method to the Tools class:
class Tools:
def Hammer(self):
return Hammer(self)
如何根据已有数据自动产生Model
使用方法非常简单:
在项目目录下的命令行中输入:
python manage.py inspectdb
或
python manage.py inspectdb > models.py
自动产生models.py文件:
- class DjangoAdminLog(models.Model):
- id = models.IntegerField(primary_key=True)
- action_time = models.DateTimeField()
- user_id = models.IntegerField()
- content_type_id = models.IntegerField(null=True, blank=True)
- object_id = models.TextField(blank=True)
- object_repr = models.CharField(maxlength=200)
- action_flag = models.TextField() # This field type is a guess.
- change_message = models.TextField()
- class Meta:
- db_table = 'django_admin_log'
Focus on creating the public interface — “views”
Philosophy
A view is a “type” of Web page in your Django application that generally serves a specific function and has a specific template. For example, in a weblog application, you might have the following views:
- Blog homepage — displays the latest few entries.
- Entry “detail” page — permalink page for a single entry.
- Year-based archive page — displays all months with entries in the given year.
- Month-based archive page — displays all days with entries in the given month.
- Day-based archive page — displays all entries in the given day.
- Comment action — handles posting comments to a given entry.
In our poll application, we’ll have the following four views:
- Poll “archive” page — displays the latest few polls.
- Poll “detail” page — displays a poll question, with no results but with a form to vote.
- Poll “results” page — displays results for a particular poll.
- Vote action — handles voting for a particular choice in a particular poll.
In Django, each view is represented by a simple Python function.
Design your URLs
format:(regular expression, Python callback function [, optional dictionary])
Default URLconf in mysite/urls.py. It also automatically set your ROOT_URLCONF setting (in settings.py) to point at that file:
ROOT_URLCONF = 'mysite.urls'
Time for an example. Edit mysite/urls.py so it looks like this:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^polls/$', 'mysite.polls.views.index'),
(r'^polls/(?P\d+)/$', 'mysite.polls.views.detail'), (r'^polls/(?P \d+)/results/$', 'mysite.polls.views.results'), (r'^polls/(?P \d+)/vote/$', 'mysite.polls.views.vote'),
)
The poll_id='23' part comes from (?P\d+) . Using parenthesis around a
pattern “captures” the text matched by that pattern and sends it as an argument
to the view function; the ?Pdefines the name that will be used to
identify the matched pattern; and \d+ is a regular expression to match a sequence of
digits (i.e., a number).
function call with parameter like this: detail(request=, poll_id='23')
Write view
Open the file mysite/app_dir/views.py and put the following Python code in it:
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the poll index.")
def detail(request, poll_id):
return HttpResponse("You're looking at poll %s." % poll_id)Each view is responsible for doing one of two things: Returning an HttpResponse
Your view can read records from a database, or not. It can use a template system
object containing the content for the requested page, or raising an exception
such as Http404. The rest is up to you.
such as Django’s — or a third-party Python template system — or not.It can generate a PDF file, output XML, create a ZIP file on the fly, anything
All Django wants is that HttpResponse. Or an exception.
you want, using whatever Python libraries you want.from mysite.polls.models import Poll
from django.http import HttpResponse
def index(request):
latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
output = ', '.join([p.question for p in latest_poll_list])
return HttpResponse(output)
from django.template import Context, loader
from mysite.polls.models import Poll
from django.http import HttpResponse
def index(request):
latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
t = loader.get_template('polls/index.html')
c = Context({
'latest_poll_list': latest_poll_list,
})
return HttpResponse(t.render(c))Raising 404
Now, let’s tackle the poll detail view — the page that displays the questionfor a given poll. Here’s the view:
from django.http import Http404# ...
def detail(request, poll_id):
try:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404
return render_to_response('polls/detail.html', {'poll': p})
A shortcut: get_object_or_404()
It’s a very common idiom to use get() and raise Http404 if the object doesn’t exist. Django provides a shortcut. Here’s the detail() view, rewritten:
from django.shortcuts import render_to_response, get_object_or_404
# ...
def detail(request, poll_id):
p = get_object_or_404(Poll, pk=poll_id)
return render_to_response('polls/detail.html', {'poll': p})
The get_object_or_404() function takes a Django model module as its first argument and an arbitrary number of keyword arguments, which it passes to the module’s get() function. It raises Http404 if the object doesn’t exist.
There’s also a get_list_or_404() function, which works just as get_object_or_404() — except using filter() instead of get(). It raises Http404 if the list is empty.Simplifying the URLconfs
Take some time to play around with the views and template system. As you edit the URLconf, you may notice there’s a fair bit of redundancy in it:
urlpatterns = patterns('',
(r'^polls/$', 'mysite.polls.views.index'),
(r'^polls/(?P\d+)/$', 'mysite.polls.views.detail'),
(r'^polls/(?P\d+)/results/$', 'mysite.polls.views.results'),
(r'^polls/(?P\d+)/vote/$', 'mysite.polls.views.vote'),
)
Namely, mysite.polls.views is in every callback.
Because this is a common case, the URLconf framework provides a shortcut for common prefixes. You can factor out the common prefixes and add them as the first argument to patterns(), like so:
urlpatterns = patterns('mysite.polls.views',
(r'^polls/$', 'index'),
(r'^polls/(?P\d+)/$', 'detail'),
(r'^polls/(?P\d+)/results/$', 'results'),
(r'^polls/(?P\d+)/vote/$', 'vote'),
)
This is functionally identical to the previous formatting. It’s just a bit tidier.
Decoupling the URLconfs
While we’re at it, we should take the time to decouple our poll-app URLs from our Django project configuration. Django apps are meant to be pluggable — that is, each particular app should be transferrable to another Django installation with minimal fuss.
Our poll app is pretty decoupled at this point, thanks to the strict directory structure that python manage.py startapp created, but one part of it is coupled to the Django settings: The URLconf.
We’ve been editing the URLs in mysite/urls.py, but the URL design of an app is specific to the app, not to the Django installation — so let’s move the URLs within the app directory.
Copy the file mysite/urls.py to mysite/polls/urls.py. Then, change mysite/urls.py to remove the poll-specific URLs and insert an include():
(r'^polls/', include('mysite.polls.urls')),
include(), simply, references another URLconf. Note that the regular expression doesn’t have a $ (end-of-string match character) but has the trailing slash. Whenever Django encounters include(), it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLconf for further processing.
Here’s what happens if a user goes to “/polls/34/” in this system:
- Django will find the match at '^polls/'
- It will strip off the matching text ("polls/") and send the remaining text — "34/" — to the ‘mysite.polls.urls’ urlconf for further processing.
Now that we’ve decoupled that, we need to decouple the ‘mysite.polls.urls’ urlconf by removing the leading “polls/” from each line:
urlpatterns = patterns('mysite.polls.views',
(r'^$', 'index'),
(r'^(?P\d+)/$', 'detail'),
(r'^(?P\d+)/results/$', 'results'),
(r'^(?P\d+)/vote/$', 'vote'),
)
The idea behind include() and URLconf decoupling is to make it easy to plug-and-play URLs. Now that polls are in their own URLconf, they can be placed under “/polls/”, or under “/fun_polls/”, or under “/content/polls/”, or any other URL root, and the app will still work.
All the poll app cares about is its relative URLs, not its absolute URLs.
Activate the admin site
The Django admin site is not activated by default — it’s an opt-in thing. To activate the admin site for your installation, do these three things:
- Add "django.contrib.admin" to your INSTALLED_APPS setting.
- Run python manage.py syncdb. Since you have added a new application to INSTALLED_APPS, the database tables need to be updated.
- Edit your mysite/urls.py file and uncomment the line below “Uncomment this for admin:”. This file is a URLconf; we’ll dig into URLconfs in the next tutorial. For now, all you need to know is that it maps URL roots to applications.
class Poll(models.Model):
# ...
class Admin:
pass
class Admin:fields = (
(None, {'fields': ('question',)}),
('Date information', {'fields': ('pub_date',), 'classes': 'collapse'}),
)
poll = models.ForeignKey(Poll, edit_inline=models.STACKED, num_in_admin=3)
choice = models.CharField(maxlength=200, core=True)
votes = models.IntegerField(core=True)
poll = models.ForeignKey(Poll, edit_inline=models.TABULAR, num_in_admin=3)
Customize the admin change list
class Poll(models.Model):
# ...
class Admin:
# ...
list_display = ('question', 'pub_date')
list_display = ('question', 'pub_date', 'was_published_today')
#was_published_today custom method
def was_published_today(self):
return self.pub_date.date() == datetime.date.today()
was_published_today.short_description = 'Published today?'
list_filter = ['pub_date']
search_fields = ['question']
date_hierarchy = 'pub_date'
detail see: http://www.djangoproject.com/documentation/model-api/
Customize the admin look and feel
Clearly, having “Django administration” and “example.com” at the top of each admin page is ridiculous. It’s just placeholder text.
That’s easy to change, though, using Django’s template system. The Django admin is powered by Django itself, and its interfaces use Django’s own template system. (How meta!)
Open your settings file (mysite/settings.py, remember) and look at the TEMPLATE_DIRS setting. TEMPLATE_DIRS is a tuple of filesystem directories to check when loading Django templates. It’s a search path.
By default, TEMPLATE_DIRS is empty. So, let’s add a line to it, to tell Django where our templates live:
TEMPLATE_DIRS = (
"/home/my_username/mytemplates", # Change this to your own directory.
)
Now copy the template admin/base_site.html from within the default Django admin template directory (django/contrib/admin/templates) into an admin subdirectory of whichever directory you’re using in TEMPLATE_DIRS. For example, if your TEMPLATE_DIRS includes "/home/my_username/mytemplates", as above, then copy django/contrib/admin/templates/admin/base_site.html to /home/my_username/mytemplates/admin/base_site.html. Don’t forget that admin subdirectory.
Then, just edit the file and replace the generic Django text with your own site’s name and URL as you see fit.
Note that any of Django’s default admin templates can be overridden. To override a template, just do the same thing you did with base_site.html — copy it from the default directory into your custom directory, and make changes.
Astute readers will ask: But if TEMPLATE_DIRS was empty by default, how was Django finding the default admin templates? The answer is that, by default, Django automatically looks for a templates/ subdirectory within each app package, for use as a fallback. See the loader types documentation for full information.
Customize the admin index page
On a similar note, you might want to customize the look and feel of the Django admin index page.
By default, it displays all available apps, according to your INSTALLED_APPS setting. But the order in which it displays things is random, and you may want to make significant changes to the layout. After all, the index is probably the most important page of the admin, and it should be easy to use.
The template to customize is admin/index.html. (Do the same as with admin/base_site.html in the previous section — copy it from the default directory to your custom template directory.) Edit the file, and you’ll see it uses a template tag called {% get_admin_app_list as app_list %}. That’s the magic that retrieves every installed Django app. Instead of using that, you can hard-code links to object-specific admin pages in whatever way you think is best.
Django offers another shortcut in this department. Run the command python manage.py adminindex polls to get a chunk of template code for inclusion in the admin index template. It’s a useful starting point.
For full details on customizing the look and feel of the Django admin site in general, see the Django admin CSS guide.
Saturday, June 16, 2007
Begin Django.
Creating a project
run the command django-admin.py startproject mysite. This will create a mysite directory in your current directory.The development server
Let’s verify this worked. Change into the mysite directory, if you haven’t already, and run the command python manage.py runserver.
Now that the server’s running, visit http://127.0.0.1:8000/ with your Web browser. You’ll see a “Welcome to Django” page, in pleasant, light-blue pastel. It worked!Changing the port
By default, the runserver command starts the development server on port 8000. If you want to change the server’s port, pass it as a command-line argument. For instance, this command starts the server on port 8080:
python manage.py runserver 8080Full docs for the development server are at django-admin documentation.
Database setup
Now, edit settings.py. It’s a normal Python module with module-level variables representing Django settings. Change these settings to match your database’s connection parameters:
- DATABASE_ENGINE — Either ‘postgresql_psycopg2’, ‘mysql’ or ‘sqlite3’. Other backends are also available.
- DATABASE_NAME — The name of your database, or the full (absolute) path to the database file if you’re using SQLite.
- DATABASE_USER — Your database username (not used for SQLite).
- DATABASE_PASSWORD — Your database password (not used for SQLite).
- DATABASE_HOST — The host your database is on. Leave this as an empty string if your database server is on the same physical machine (not used for SQLite).
sudo aptitude install python-psycopg2
By default, INSTALLED_APPS contains the following apps, all of which come with Django:
- django.contrib.auth — An authentication system.
- django.contrib.contenttypes — A framework for content types.
- django.contrib.sessions — A session framework.
- django.contrib.sites — A framework for managing multiple sites with one Django installation.
These applications are included by default as a convenience for the common case.
Each of these applications makes use of at least one database table, though, so we need to create the tables in the database before we can use them. To do that, run the following command:
python manage.py syncdb
For the minimalists
Like we said above, the default applications are included for the common case, but not everybody needs them. If you don’t need any or all of them, feel free to comment-out or delete the appropriate line(s) from INSTALLED_APPS before running syncdb. The syncdb command will only create tables for apps in INSTALLED_APPS.
Creating models
Projects vs. apps
What’s the difference between a project and an app? An app is a Web application that does something — e.g., a weblog system, a database of public records or a simple poll app. A project is a collection of configuration and apps for a particular Web site. A project can contain multiple apps. An app can be in multiple projects.
python manage.py startapp polls
Edit the polls/models.py file so it looks like this:
from django.db import models
class Poll(models.Model):
question = models.CharField(maxlength=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice = models.CharField(maxlength=200)
votes = models.IntegerField()
- python manage.py sql polls
- python manage.py validate polls — Checks for any errors in the construction of your models.
- python manage.py sqlcustom polls — Outputs any custom SQL statements (such as table modifications or constraints) that are defined for the application.
- python manage.py sqlclear polls — Outputs the necessary DROP TABLE statements for this app, according to which tables already exist in your database (if any).
- python manage.py sqlindexes polls — Outputs the CREATE INDEX statements for this app.
- python manage.py sqlall polls — A combination of all the SQL from the ‘sql’, ‘sqlcustom’, and ‘sqlindexes’ commands.
Now, run syncdb again to create those model tables in your database:
python manage.py syncdbhttp://www.djangoproject.com/documentation/db-api/
PostgreSQL
一直习惯于Redhat FreeBSD下postgresql的安装,这次用了一台Ubuntu的server,让经典的sudo命令给忽悠了一下,走了几个弯路,特此记下。同时该步骤也可供debian用户参考。
- 安装:
sudo apt-get install postgresql-8.1 #安装8.1版本的pgsql
sudo /etc/init.d/postgresql-8.1 restart - 添加数据库用户,正是这一条指令让我郁闷——Ubuntu中默认的pgsql安装,postgres用户不能su的,但创建数据库用户必须使用postgres帐户操作,于是就成了:
sudo -u postgres createuser -P YOURNAME
强烈建议配置密码,一来为了安全,二来也是为了以后方便配置 - 创建用户名对应的数据库
sudo -u postgres createdb YOURNAME - 登录测试
psql -U YOURNAME
最后,关于pgsql无法远程访问的问题:修改/etc/postgresql/8.1/main中的“#listen_addresses = 'localhost'”为“listen_addresses = '*‘”重新启动即可
Tuesday, June 5, 2007
split String into Chinese Symbol and English Word.
# _zhstr , _asstr 存储 中文,非中文 数组
_zhstr = []
_asstr = []
def _fenzhas(stri):
''' 分开中文和非中文,
存入全局数组 _zhstr , _asstr
'''
global _asstr
global _zhstr
ln = len(stri)
_zhstr = []
_asstr = []
n = 0
m = 0
try:
stri[n] >= u'\u4e00'
except:
return 0
while n < ln:
if stri[n] >= u'\u4e00':
if m==0:_zhstr.append(' ')
_zhstr.append(stri[n])
## print 'z:',stri[n]
m=1
else:
if m==1:_asstr.append(' ')
_asstr.append(stri[n])
## print 'a:',stri[n]
m=2
n+=1
Converter CJK Encoding to Unicode
encc = ""
def zh2unicode(stri):
"""Auto converter encodings to unicode
global encc
for c in ('utf-8', 'gbk', 'big5', 'jp', 'euc_kr','utf16','utf32'):
encc = c
try:
return stri.decode(c)
except:
pass
encc = 'unk'
return stri
Logitech Mouse 4 Way Scrollbutton.
Section "InputDevice"
Identifier "Configured Mouse"
Driver "evdev"
Option "Dev Name" "Logitech USB Optical Mouse"
Option "CorePointer"
Option "Device" "/dev/input/event2"
Option "Buttons" "7"
Option "ZAxisMapping" "4 5 6 7"
EndSection
ps: Information of Option "Device" comes from /proc/bus/input/devices
For Logitech RX1000:
Section "InputDevice"
Identifier "Configured Mouse"
Driver "evdev"
Option "Dev Name" "Logitech USB Optical Mouse"
Option "CorePointer"
Option "Buttons" "8"
Option "ZAxisMapping" "4 5 6 7"
Option "Resolution" "1000"
EndSection
Ubuntu Guide Feisty Fawn (chinese)
http://wiki.ubuntu.org.cn/index.php?title=%E5%BF%AB%E9%80%9F%E8%AE%BE%E7%BD%AE%E6%8C%87%E5%8D%97/FeistyFawn&variant=zh-cn
third party source for libdvdcss2 and w32codecs
deb http://medibuntu.sos-sts.com/repo/ feisty free non-freekey:
deb-src http://medibuntu.sos-sts.com/repo/ feisty free non-free
wget -q http://packages.medibuntu.org/medibuntu-key.gpg -O- | sudo apt-key add -then:
sudo apt-get update
sudo apt-get install w32codecs libdvdcss2
Saturday, June 2, 2007
NvidiaLaptopBinaryDriverSuspend
Section "Device"
...
Option "NvAGP" "1"
EndSection
/etc/default/acpi-support
...
# Should we attempt to warm-boot the video hardware on resume?
POST_VIDEO=false
...
Swap and Hibernation problem
However feisty seems to have a problem with this naming method and swap partitions on some installations. Do $ sudo free
to check if your swap partition is used. If the line with swap it it just returns three times "0", your swap partition is not being used and you are most probably affected by bug 66637. The problem is that your system generates a new UUID for your swap partition on every reboot. Your old settings in the fstab then cannot be used anymore and your system does not use any swap. Without swap hibernate (suspend to disk) does not work either (standby/suspend to RAM still does).
Follow these instructions to fix this
- determine your swap with
$ sudo fdisk -l
. In my case it was /dev/sda2 - do mkswap on your swap partition and record the uuid which this command outputs, e.g.
$ sudo mkswap /dev/sda2
- now use this UUID to put into fstab: Look for the line with the swap partition and replace the old UUID with the new one:
$ sudo gedit /etc/fstab
- add the same UUID intu your resume file:
$ sudo gedit /etc/initramfs-tools/conf.d/resume
; the file should only look like this: "RESUME=UUID=" - do
$ update-initramfs -u
- update your grub configuration; edit it with
$ sudo gedit /boot/grub/menu.lst
and look for the line that says "# defoptions=quiet splash" and change it to "# defoptions=quiet splash resume=" - reboot normally. After this test with
$ sudo free
or with$ swapon -s
if your swap is now activated - Now you can test hibernate, too.
Thanks to various people on the bug thread.