以一个投票程序的实例来讲解Python的Django框架使
这篇文章主要介绍了以一个投票程序的实例来讲解Python的Django框架使用,Django是Python世界中人气最高的MVC框架,需要的朋友可以参考下
(一)关于Django
Django是一个基于MVC构造的框架。但是在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),称为 MTV模式。
Ubuntu下的安装:一般都自带Python的。网上教程比较多了....
1
2
3
4
5
6
7
8
|
dizzy@dizzy-pc:~$ python Python 2.7.3 (default, Apr 20 2012, 22:44:07) [GCC 4.6.3] on linux2 Type "help" , "copyright" , "credits" or "license" for more information. >>> import django >>> help(django) VERSION = (1, 6, 4, 'final' , 0) #可以查看django版本等信息。 |
(二)第一个Django的app
#环境:Python2.7,Django1.6,Ubuntu12.04
Python 及 Django 安装成功之后,就可以创建Django工程了
(1)教你开始写Django1.6的第1个app
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
#先创建一个文件夹 dizzy@dizzy-pc:~$ mkdir Python dizzy@dizzy-pc:~$ cd Python #然后创建工程 dizzy@dizzy-pc:~ /Python $ django-admin.py startproject mysite dizzy@dizzy-pc:~ /Python $ cd mysite #然后这个工程就可以启动服务了 dizzy@dizzy-pc:~ /Python/mysite $ python manage.py runserver Validating models... 0 errors found July 23, 2014 - 14:17:29 Django version 1.6.4, using settings 'mysite.settings' Starting development server at http: //127 .0.0.1:8000/ Quit the server with CONTROL-C. #这样,打开浏览器访问: 便可看到: It Worked! 关闭服务:ctrl+c #新创建的项目里面会有:manage.py文件,mysite文件夹 #在mysite文件夹里面会有:__init__.py,settings.py,urls.py,wsgi.py四个文件 #__init__.py是一个空文件, #setting.py 是项目的配置文件。需要修改两个地方,这里使用默认的SQLite3数据库 LANGUAGE_CODE = 'zh-cn' #原:en-us TIME_ZONE = 'Asia/Shanghai' #原:UTC #配置完之后,便可以创建数据表了 dizzy@dizzy-pc:~ /Python/mysite $ python manage.py syncdb #创建是还要设置一个超级管理员,用于后台登录。 #设置完之后,开启服务,便可进入后台管理界面了:http://127.0.0.1:8000/admin/ |
(2)教你开始写Django1.6的第1个app
1
2
3
4
5
6
7
|
#创建一个用于投票的app。 #进入mysite工程根目录,创建app dizzy@dizzy-pc:~ /Python/mysite $ python manage.py startapp polls dizzy@dizzy-pc:~ /Python/mysite $ ls polls admin.py __init__.py models.py urls.py views.py #这样。Django已经生成了,app通常所需的模板文件。 |
下面创建两个models。Poll 和 Choice
1
|
dizzy@dizzy-pc:~ /Python/mysite $ vim polls /models .py |
修改文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
from django.db import models # Create your models here. from django.db import models class Poll(models.Model): question = models.CharField(max_length = 200 ) pub_date = models.DateTimeField( 'date published' ) class Choice(models.Model): poll = models.ForeignKey(Poll) choice_text = models.CharField(max_length = 200 ) votes = models.IntegerField(default = 0 ) #基本创建model过程就是这样,细节还要深入研究! |
然后修改工程的配置文件setting.py,在INSTALLED_APP元组下面添加刚才创建的app:polls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
dizzy@dizzy - pc:~ / Python / mysite$ vim mysite / settings.py INSTALLED_APPS = ( 'django.contrib.admin' , 'django.contrib.auth' , 'django.contrib.contenttypes' , 'django.contrib.sessions' , 'django.contrib.messages' , 'django.contrib.staticfiles' , 'polls' , ) #可以使用 python manage.py sql polls 查看app的建表SQL #使用 python manage.py syncdb 进行创建数据库表 dizzy@dizzy - pc:~ / Python / mysite$ . / manage.py sql polls BEGIN; CREATE TABLE "polls_poll" ( "id" integer NOT NULL PRIMARY KEY, "question" varchar( 200 ) NOT NULL, "pub_date" datetime NOT NULL ) ; CREATE TABLE "polls_choice" ( "id" integer NOT NULL PRIMARY KEY, "poll_id" integer NOT NULL REFERENCES "polls_poll" ( "id" ), "choice_text" varchar( 200 ) NOT NULL, "votes" integer NOT NULL ) ; COMMIT; #这样就可以通过设置model让Django自动创建数据库表了 要想在后台admin中管理polls。还需要修改app下面的admin.py 文件。 from django.contrib import admin # Register your models here. from django.contrib import admin from polls.models import Choice,Poll class ChoiceInLine(admin.StackedInline): model = Choice extra = 3 class PollAdmin(admin.ModelAdmin): fieldsets = [ ( None , { 'fields' :[ 'question' ]}), ( 'Date information' , { 'fields' :[ 'pub_date' ], 'classes' :[ 'collapse' ]}), ] inlines = [ChoiceInLine] admin.site.register(Poll,PollAdmin) #这部分代码,大体能看懂,具体的规则还要稍后的仔细研究。 ##这部分代码,由于拼写失误,导致多处出错。细节决定成败!! |
这样再重启服务,就能在后台管理polls应用了。
(3)视图和控制器部分
前面已经完成了model(M)的设置。剩下的只有view(V)和urls(C)了。Django的视图部分,由views.py 和 templates完成。
在polls中,我们将创建4个视图:
- “index” 列表页 – 显示最新投票。
- “detail” 投票页 – 显示一个投票的问题, 以及用户可用于投票的表单。
- “results” 结果页 – 显示一个投票的结果。
- 投票处理 – 对用户提交一个投票表单后的处理。
现在修改 views.py 创建用于视图的函数。
1
|
dizzy@dizzy-pc:~ /Python/mysite $ vim polls /views .py |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
from django.shortcuts import render,get_object_or_404 # Create your views here. from django.http import HttpResponse from polls.models import Poll def index(request): latest_poll_list = Poll.objects. all ().order_by( '-pub_date' )[: 5 ] context = { 'latest_poll_list' :latest_poll_list} return render(request, 'polls/index.html' ,context) def detail(request,poll_id): poll = get_object_or_404(Poll,pk = poll_id) return render(request, 'polls/detail.html' ,{ 'poll' :poll}) def results(request,poll_id): return HttpResponse( "you're looking at the results of poll %s." % poll_id) def vote(request,poll_id): return HttpResponse( "you're voting on poll %s." % poll_id) #涉及Django的自带函数,不做深究。后面再做研究! |
要想使试图能被访问,还要配置 urls.py 。mysite是整个网站的URLConf,但每个app可以有自己的URLConf,通过include的方式导入到根配置中即可。现在在polls下面新建 urls.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
from django.conf.urls import patterns,url from polls import views urlpatterns = patterns('', #ex:/polls/ url(r '^$' ,views.index,name = 'index' ), #ex:/polls/5/ url(r '^(?P<poll_id>\d+)/$' ,views.detail,name = 'detail' ), #ex:/polls/5/results/ url(r '^(?P<poll_id>\d+)/results/$' ,views.results,name = 'results' ), #ex:/polls/5/vote/ url(r '^(?P<poll_id>\d+)/vote/$' ,views.vote,name = 'vote' ), ) #url中,三个参数。正则的url,处理的函数,以及名称 #正则表达式!!!!! |
然后在根 urls.py 文件中,include这个文件即可。
1
|
dizzy@dizzy-pc:~ /Python/mysite $ vim mysite /urls .py |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', # Examples: # url(r'^$', 'mysite.views.home', name='home'), # url(r'^blog/', include('blog.urls')), url(r '^polls/' , include( 'polls.urls' ,namespace = "polls" )), url(r '^admin/' , include(admin.site.urls)), ) #有Example:两种形式。因为是元组,所以开始有“ ‘', ”。 |
然后开始创建模板文件。在polls下,创建templates文件夹。下面有index.html, detail.html 两个文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<!-- index.html --> {% if latest_poll_list %} <ul> {% for poll in latest_poll_list %} <li><a href="{% url 'polls:detail' poll_id=poll.id %}">{{ poll.question }}</a></li> {% endfor %} </ul> {% else %} <p>No polls are available.</p> {% endif %} <!--detail.html--> <h1>{{ poll.question }}</h1> <ul> {% for choice in poll.choice_set.all %} <li>{{ choice.choice_text }}</li> {% endfor %} </ul> <!-- 视图设置完毕,具体语法还要深入研究! --> <!-- 现在重启服务, 便可看到相应视图 --> |
(4)投票功能完善
上面只是简单的实现了视图功能,并没有真正的实现投票功能。接下来就是完善功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#修改模板文件 dizzy@dizzy - pc:~ / Python / mysite$ vim polls / templates / polls / detail.html #需要加入form表单 <h1>{{ poll.question }}< / h1> { % if error_message % }<p><strong>{{ error_message }}< / strong>< / p>{ % endif % } <form action = "{% url 'polls:vote' poll.id %}" method = "post" > { % csrf_token % } { % for choice in poll.choice_set. all % } < input type = "radio" name = "choice" id = "choice{{ forloop.counter }}" value = "{{ choice.id }}" / > <label for = "choice{{ forloop.counter }}" >{{ choice.choice_text }}< / label><br / > { % endfor % } < input type = "submit" value = "Vote" / > < / form> |
然后需要修改 views.py 中的 vote 处理函数。进行post数据的接收与处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# 文件 polls/views.py from django.shortcuts import get_object_or_404, render from django.http import HttpResponseRedirect, HttpResponse from django.core.urlresolvers import reverse from polls.models import Choice, Poll # ... def vote(request, poll_id): p = get_object_or_404(Poll, pk = poll_id) try : selected_choice = p.choice_set.get(pk = request.POST[ 'choice' ]) except (KeyError, Choice.DoesNotExist): # Redisplay the poll voting form. return render(request, 'polls/detail.html' , { 'poll' : p, 'error_message' : "You didn't select a choice." , }) else : selected_choice.votes + = 1 selected_choice.save() # Always return an HttpResponseRedirect after successfully dealing # with POST data. This prevents data from being posted twice if a # user hits the Back button. return HttpResponseRedirect(reverse( 'polls:results' , args = (p. id ,))) |
在投票成功之后,让用户浏览器重定向到结果 results.html 页。
1
2
3
|
def results(request, poll_id): poll = get_object_or_404(Poll, pk = poll_id) return render(request, 'polls/results.html' , { 'poll' : poll}) |
然后就需要创建模板 results.html 。
1
2
3
4
5
6
7
8
9
10
11
|
<!-- polls/templates/polls/results.html --> <h1>{{ poll.question }}</h1> <ul> {% for choice in poll.choice_set.all %} <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li> {% endfor %} </ul> <a href="{% url 'polls:detail' poll.id %}">Vote again?</a> |
至此,重启服务就能看到单选按钮,以及submit了。