杂谈
学习历程
从学了Python以来,我都一直想着用它来做点什么。从开始用python来写简单的工具脚本,然后再是网络信息抓取程序。
听说可以用Python来做网站,所以我了解了一下web.py与Django。第一次接触Django,由于没有网络方面的基础,所以没弄两下就放弃了。
后来,我研究了一下Python自来的SimpleHTTPServer,然后读懂了CGIHTTPServer,才对Web的实质有了了解。
在这个基础上,我再次重拾Django。这次,终于学会了。
原来它是那么的美妙!
相关书籍
我看的是《Python+Django+Web开发指南》,下的电子书。
示例代码
本博文相关的Blog代码已提交到:http://git.oschina.net/hevake_lcj/Django-Blog
学习笔记
1. 安装
下载源码文件: Django-1.6.10.tar.gz
解压后生成目录:Django-1.6.10
进入目录
执行:sudo python setup.py install
就完成安装
安装完成之后,当前目录下的django目录会被copy到python的库目录下的site-packages中。
2. 创建工程
执行: django-admin.py startproject <工程名>
完成后会在当前目录下生成<工程名>,比如mysite,的目录。在该目录下会有:
. |-- manage.py `-- mysite |-- __init__.py |-- settings.py |-- urls.py `-- wsgi.py
其中manage.py管理工具,之后的管理工作都是通过它来完成。
3. 运行网站
$ ./manage.py runserver Validating models... 0 errors found March 02, 2015 - 11:33:33 Django version 1.6.10, using settings ‘mysite.settings‘ Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C. [02/Mar/2015 11:33:45] "GET / HTTP/1.1" 200 1757
默认端口为8000
用本地浏览器访问: 127.0.0.1:8000
4. 创建应用
$ ./manage.py startapp <应用名>
应用名可以随便取,但要符合python标识符的命名规范。比如:blog
在创建之后,在当前目录(manager.py所在目录)下生成blog目录。内容如下:
. |-- admin.py |-- __init__.py |-- models.py |-- tests.py |-- urls.py #python3没有,可以自己建 `-- views.py
4.1 将应用加入到mysite
编辑mysite/settings.py
在INSTALLED_APPS中加入blog
INSTALLED_APPS = ( ‘django.contrib.admin‘, ‘django.contrib.auth‘, ...(略) ‘blog‘ )
4.2 配置数据库
还要配置数据库,告诉mysite用什么数据库。同样是在settings.py中,配置DATABASES
DATABASES = { ‘default‘ : { ‘ENGINE‘ : ‘django.db.backends.sqlite3‘, ‘NAME‘ : os.path.join(BASE_DIR, ‘db.sqlite3‘), } }
默认配置是sqlite3,当然也可以用其它的数据库,如mysql。
如下是mysql的配置:
DATABASES = { ‘default‘ : { ‘ENGINE‘ : ‘django.db.backends.mysql‘, ‘NAME‘ : ‘djangodb‘, ‘HOST‘ : ‘localhost‘, ‘USER‘ : ‘paul‘, ‘PASSWORD‘ : ‘pony‘ # secret! } }
由于系统自带sqlite3,那就用默认的吧。
4.3 models.py中定义模型
在mysite/blog/models.py中实义数据库对应的模型。
比如:
from django.db import models class BlogPost(models.Model): title = models.CharField(max_length=150) body = models.TextField() timestamp = models.DateTimeField()
上面就定义了一个BlogPost的模型。其对应数据库的一张名为blog_blog_post的表。
BlogPost中的每个属性对应着表中的一个Field,也就是列。比如上面的:title, body, timestamp。
而这些属性所对应的对象着表明了域的特性。
models.CharField ---> char[n]
models.TextField ---> text
models.DateTimeField ---> DateTime
models.BooleanField ---> bool
models.IntegerField ---> int
要使用上面的这些models,必须得from django.db imports models
django.db.models中的Model定义在: lib/pythonx.x/site-packages/django/db/models/fields/__init__.py 中。
注:在对models.py进行修改之后都要同步一下数据库。
$ python manage.py syncdb Creating tables ... Creating table django_admin_log Creating table auth_permission Creating table auth_group_permissions Creating table auth_group Creating table auth_user_groups Creating table auth_user_user_permissions Creating table auth_user Creating table django_content_type Creating table django_session Creating table blog_blogpost You just installed Django‘s auth system, which means you don‘t have any superusers defined. Would you like to create one now? (yes/no): yes #输入yes Username (leave blank to use ‘hevake_lcj‘): sa #管理员帐户 Email address: Password: #设置密码 Password (againUsername (leave blank to use ‘hevake_lcj‘): sa Email address: Password: Password (again): Superuser created successfully. Installing custom SQL ... Installing indexes ... Installed 0 object(s) from 0 fixture(s)): Superuser created successfully. Installing custom SQL ... Installing indexes ... Installed 0 object(s) from 0 fixture(s)
4.3.1 将model加入到admin管理
在定义了Person之后,如果想要让admin工具管理。那么就得注册。
打开mysite/blog/admin.py
from django.contrib import admin from models import * #导入models.py admin.site.register(BlogPost)
这样以来,开启服务后,我们就可以通过访问: http://127.0.0.1:8000/admin/blog/
输入刚刚设定的帐号密码,然后Login登陆。
点Blog posts,进去添加一个Model对象。
保存Save。
路径上管理我们的BlogPost模型了。
Django中的admin不是其必须的模块,但是它是管理网站很有用的工具。
4.3.2 指定admin页面列表中要显示的域
但是,上面这么做还不能很好在地admin的blog_post页面展现我们的BlogPost对象。显示的是“BlogPost object”
因为admin并不知道该怎么显示到列表上。
为了在admin的网面上更好地展现,通常我们要为model(如:BlogPost)添加一个Admin类进行管理,指定哪些域要显示的网页列表上。
打开mysite/blog/admin.py文件,添加BlogPostAdmin类,如下:
class BlogPostAdmin(admin.ModelAdmin): list_display = (‘title‘, ‘timestamp‘)
在这个类中有一个list_display属性,说明列表中要显示的是title与timestamp两个域。
然后将原来的:
admin.site.register(BlogPost)
改成:
admin.site.register(BlogPost, BlogPostAdmin) # ^^^^^^^^^^^^^
然后,我们再刷新一下刚刚的页面:http://127.0.0.1:8000/admin/blog/blogpost/
4.4 添加html模板
在 blog/ 目录下新建 templates 目录,所有的模板都是从template目录下去查找的。
blog |-- templates `-- archive.html
在mysite/blog/templates/目录创建一个模板archive.html
{% for post in posts %} <h2>{{ post.title }}</h2> <p>{{ post.timestamp }}</p> <p>{{ post.body }}</p> {% endfor %}
模板的功能是用于描述如何生成html文件。
当接受到请求时,view会将template与model进行结合生成对应的html文件。
4.5 添加view
在例子中view的功能更像是请求处理函数。它接受请求,并返回生成的html正文。
编辑mysite/blog/views.py
from django.template import loader, Context from django.http import HttpResponse from models import BlogPost def archive(request): posts = BlogPost.objects.all() #从数据库获取所有的BlogPost对象 t = loader.get_template("archive.html") #用loader从mysite/blog/templates/目录下找出名为archive.html的模板 c = Context({‘posts‘: posts}) return HttpResponse(t.render(c))
上面的过程过于复杂,可以用render_to_response()来简化过程
from django.shortcuts import render_to_response from django.http import HttpResponse from models import BlogPost def archive(request): posts = BlogPost.objects.all() return render_to_response(‘archive.html‘, {‘posts‘:posts})
4.6 添加url模式
上面在views.py中定义了如何响应请求。哪个如何将一个请求路径与view中的archive
对应呢?那就是在urls.py中指定了。
我们打开mysite/urls.py,并作如下修改:
from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns(‘‘, url(r‘^admin/‘, include(admin.site.urls)), url(r‘^blog/‘, include(‘blog.urls‘)) #这行是刚加的 )
在urlpatterns中添加url(r‘^blog/‘, include(‘blog.urls‘)),说明凡是以blog/开头的路径都由 blog.urls 模块中的 urlpatterns 进行分派。
现在我们来建 blog/目录下的 urls.py 文件
from django.conf.urls import patterns, url from blog.views import * urlpatterns = patterns(‘‘, url(r‘^$‘, archive) )
在blog/urls.py中指定,blog/下的所有请求者交给view.archive处理。
如此以来,从请求到响应就连成了一条完整的流程。
好!我们来检验一下成果!访问:http://127.0.0.1:8000/blog/
4.7 排序
虽然达到了最初的目的,但是顺序最好是按时间倒序排列。
在 blog/models.py 中的 BlogPost 类中添加 Meta 内部类,用这个内部类指定排库方式
class BlogPost(models.Model): timestamp = models.DateTimeField() # 略... class Meta: ordering = (‘-timestamp‘,)
上面指定以timestamp进行逆排序。
这就对了嘛!
5. 总结
Django是一个MTV(模型、模板、视图)的web设计架构。
当服务器运行起来之后,每接收到一个http请求,则通过urls.py中的模式匹配,找到对应的view来处理。
view找到对应的template并将models中的数据填充到template中生成html数据再返回给用户。
与之前了解的CGIHTTPServer不同的是,CGIHTTPServer只是一个有CGI功能的HTTP服务器,只负责将HTTP请求指定到对应的cgi文件,它并不管cgi是怎么实现一个页面的。
而Django则是在wsgi的基础上进一步对封装。为具体实现逻辑提供许多非常有用的工具,并提出一个很有用的框架,它是服务器+架构。
6. 下集预告
明天将会与大家一起深入地学习Django的模型,尽情关注!