Django快速入门

作者:Adam at 2016-10-29 12:53:26
(注:本教程来源于官方最新Django教程)

作为一名前端开发,了解后端技术很有必要。作为一名web程序员,掌握web开发全栈技能,成为未来发展的必然趋势。既然聘宝的研发以Python开发为主,我们有必要先学习一下Django这个开发框架。

首先,为了快速进入学习,我们假设你已经安装好聘宝研发的Python+Docker开发环境。接着我们建立虚拟开发环境。

1
2
3
4
5
6
➜ ~ mkdir myFirstDjango
➜ ~ cd myFirstDjango
➜ myFirstDjango mkvirtualenv myFirstDjango
New python executable in myFirstDjango/bin/python
Installing setuptools, pip, wheel...done.
(myFirstDjango)➜ myFirstDjango

安装Django

1
2
3
4
5
6
7
8
(myFirstDjango)➜ myFirstDjango pip install django
You are using pip version 7.1.0, however version 8.1.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Collecting django
Downloading http://pypi.doubanio.com/packages/8a/09/46f790104abca7eb93786139d3adde9366b1afd59a77b583a1f310dc8cbd/Django-1.10.2-py2.py3-none-any.whl (6.8MB)
100% |████████████████████████████████| 6.8MB 1.5MB/s
Installing collected packages: django
Successfully installed django-1.10.2

创建一个项目mysite

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
(myFirstDjango)➜ django-admin startproject mysite
项目文件列表
------------------
mysite/ 项目名称
manage.py 命令行工具
mysite/ 代码目录
__init__.py 模块化申明文件,一般为空
settings.py 配置文件
urls.py 路由配置文件
wsgi.py 服务器文件
启动本地开发环境:
------------------
(myFirstDjango)➜ myFirstDjango cd mysite && python manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
You have 13 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
October 29, 2016 - 05:47:37
Django version 1.10.2, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
启动前需要用 migrate 做些数据库迁移修复工作:
------------------
(myFirstDjango)➜ mysite python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying sessions.0001_initial... OK
再次启动开发环境:
------------------
(myFirstDjango)➜ python manage.py runserver 0.0.0.0:8000

浏览器访问: http://127.0.0.1:8000/

第一步完成了,我们还需要澄清一个细节,注意看这两个命令:

django-admin startprojectpython manage.py startapp polls

这里面的projectapp是有区别的:

app可以看作是一个完成功能模块,而project可以看作成一个网站,由多个功能模块app组成。关键是模块app可以被多个project直接使用,这点非常重要,DRY万岁。

我们运行python manage.py startapp polls,生成一个新的投票模块polls。可以看到mysite目录下多了一个polls目录。

1
2
3
4
5
6
7
8
9
10
11
12
mysite/
manage.py
mysite/
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py

接着,我们需要补充路由文件urls.py

1
2
3
4
5
6
#urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
]

同样在site目录下也需要补充一个:

1
2
3
4
5
6
7
#urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^polls/', include('polls.urls')), #包含polls模块的路由
url(r'^admin/', admin.site.urls),
]

同时在mysite/settings.py修改:

1
2
3
4
5
6
7
8
9
INSTALLED_APPS = [
'polls.apps.PollsConfig', #引入安装的模块
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

最后增加模版文件mysite/polls/templates/polls/index.html

1
2
3
4
5
6
7
8
{% if latest_question_list %} <ul>
{% for question in latest_question_list %}
<li><a href="/polls/{{ question.id }}/">
{{ question.question_text }}</a>
</li>
{% endfor %}
</ul> {% else %}
<p>暂无投票。</p> {% endif %}

mysite目录下,再次启动开发环境:

1
(myFirstDjango)➜ python manage.py runserver 0.0.0.0:8000

访问http://0.0.0.0:8000/polls/可以看到:

1
暂无投票。

对,还没有投票内容。我们还需要建立Model制定数据结构,添加投票数据,然后从数据库获取投票数据。

为了讲解方便我们先使用sqlite作为默认的数据库存储数据:

1
2
3
4
5
6
7
8
#mysite/settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
#数据库文件保存的位置
'NAME': os.path.join(BASE_DIR, 'db.sqlite3')
}
}

首先,编辑polls/models.py,制定Model数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from __future__ import unicode_literals
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.question_text
@python_2_unicode_compatible
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text

然后利用makemigrations工具生成数据库迁移文件polls/migrations/0001_initial.py

1
2
3
4
5
6
(myFirstDjango)➜ mysite python manage.py makemigrations polls
Migrations for 'polls':
polls/migrations/0001_initial.py:
- Create model Choice
- Create model Question
- Add field question to choice

接着执行数据库迁移操作,这里应该包含建表的操作,这样我们就可以通过管理工具添加投票数据了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(myFirstDjango)➜ mysite python manage.py sqlmigrate polls 0001
BEGIN;
--
-- Create model Choice
--
CREATE TABLE "polls_choice" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL);
--
-- Create model Question
--
CREATE TABLE "polls_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "question_text" varchar(200) NOT NULL, "pub_date" datetime NOT NULL);
--
-- Add field question to choice
--
ALTER TABLE "polls_choice" RENAME TO "polls_choice__old";
CREATE TABLE "polls_choice" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL, "question_id" integer NOT NULL REFERENCES "polls_question" ("id"));
INSERT INTO "polls_choice" ("choice_text", "votes", "id", "question_id") SELECT "choice_text", "votes", "id", NULL FROM "polls_choice__old";
DROP TABLE "polls_choice__old";
CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id");
COMMIT;
(myFirstDjango)➜ mysite

完成后可以检查下是否迁移有错误发生:

1
2
(myFirstDjango)➜ mysite python manage.py check
System check identified no issues (0 silenced).

或者直接使用migrate命令执行所有未执行的迁移操作。

1
2
3
4
5
(myFirstDjango)➜ mysite python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Applying polls.0001_initial... OK

然后我们生成后台管理界面:

1
2
3
4
5
6
(myFirstDjango)➜ mysite python manage.py createsuperuser
Username (leave blank to use 'super'): admin
Email address: yourname@gmail.com
Password:
Password (again):
Superuser created successfully.

polls/admin.py里面注册可以管理的Model:

1
2
3
from .models import Question, Choice
admin.site.register(Question)
admin.site.register(Choice)

然后访问http://0.0.0.0:8000/admin/

添加完投票内容后,

修改一下polls的路由:

1
2
3
4
5
6
app_name = 'polls'
urlpatterns = [
url(r'^$', views.index, name='index'),
# the 'name' value as called by the {% url %} template tag
url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
]

修改投票主页模版:

1
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

并且增加投票详细页的模版detail.html

1
2
3
4
5
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}</li> {% endfor %}
</ul>

访问http://0.0.0.0:8000/polls/1/,最简单的Django投票样例就完成了。

1
2
3
4
你会学习python吗?
* 会
* 不会
* 不知道

这是个非常简单的MVC架构,熟悉Angular的同学应该很快就能理解Django的做法,怎么样,Python也不难吧~