建议直接阅读末尾!!!

Writing your first Django app, part 2

本节将设置数据库,创建您的第一个模型(model),并简单介绍Django自动生成的管理页面。

数据库设置

现在,打开mysite/settings.py。这是一个普通的Python模块,代表Django配置的模块级变量。

默认情况下,配置使用SQLite。如果你初涉数据库,或者只想尝试Django,这是最简单的选择。SQLlite包含在Python中,所以你不需要安装对数据库的支持。当您开始第一个真正的项目时,您可能希望使用想 PostgreSQL这样更具扩展性的数据库,以避免数据库切换造成的头痛。

如果您想使用其他数据库,需要安装响应的数据库绑定,并配置以下DATABASES 'default'中的项目来匹配您的数据库连接:

  • ENGINE -- 可以为'django.db.backends.sqlite3', 'django.db.backends.postgresql', 'django.db.backends.mysql'或者'django.db.backends.oracle'。其他后端也允许使用
  • NAME -- 数据库的名称。如果使用SQLite,数据库就是电脑中的一个文件,那么NAME应该是该文件的完整绝对路径(包括文件名)。默认值os.path.join(BASE_DIR, 'db.sqlite3'),会将数据库文件保存在您的项目目录中。

如果不是用SQLite作为数据库,需要添加USER,PASSWORD和HOST等附加值。详细操作请参考DATABASES

还需要注意在该文件顶部的INSTALLED_APPS配置。它包含了在该Django实例中激活的所有Django应用的名称。Apps(应用)可以被多个项目使用,你可以打包并发布给其他项目。

默认情况下,INSTALLED_APPS包含以下应用,这些应用随Django一起提供:

  • django.contrib.admin -- 管理站点。你会很快用到它。
  • django.contrib.auth -- 认证系统。
  • django.contrib.contenttypes -- 内容类型的框架。
  • django.contrib.sessions -- 会话框架。
  • django.contrib.messages -- 消息框架。
  • django.contrib.staticfiles -- 管理静态文件的框架。

这些应用一般情况下被默认包含在内。

其中一些应用要使用至少一张数据表,所以我们在使用它们之前需要创建一张数据表。为此,运行一下命令:

$ python manage.py migrate

migrate命令会查看INSTALLED_APPS配置,并根据mysite/setting.py文件中的数据库配置和应用程序随附的数据迁移来创建所有必需的数据库(稍后介绍)。你将看到每个数据迁移的信息。如果你有兴趣,您可以在数据库的命令行客户端输入\dt(PostgreSQL), SHOW TABLES;(MySQL), .schema(SQLite) 或者 SELECT TABLE_NAME FROM USER_TABLES;(Oracle)来显示Django创建的数据表。

创建模型(model)

现在我们通过使用额外的元数据来来定义自己的模型(本质上就是数据库的布局)。

在我们的poll应用中,我们将创建两个模型:QuestionChoice。每个Question有一个问题和一个发布日期。每个Choice有两个字段:选择文本和投票计数器。每个Choice都和一个Question相关联。

这些概念由简单Python类表示,编辑polls/models.py文件:

 # polls/models.py

 from django.db import models

 class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published') class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)

代码很简单。每个模型都由一个继承自django.db.models.Model的子类表示。每个模型中都有一些类的变量,每个模型中的变量代表一个数据库字段。

每个字段由由Field类的实例表示,例如,CharField用于字符字段,DateTimeField用于时期。这告诉Django每个字段代表什么类型的数据。

每个Field实例的名称(例如question_text, pub_date)就是字段的名称(以机器友好的格式书写)。你将在Python代码中使用这些值,你的数据库将使用它作为列名称。

你可以使用可选的第一个位置参数来给Field指定一个方便人理解(human-readable)的名称。这用于Django的几个内省的部分,它可以作为文档。如果该字段没有提供,Django将使用机器刻度(machine-readable)的名称。在本例中,我们只为Question.pub_date字段定义了人类的可读(human-readable)的名称。本例中的其他字段,字段的机器名称足够作为人类可读的名称。(翻译完这段感觉自己已经成仙了/(ㄒoㄒ)/~~)

一些Field类有必要的参数。例如CharField,要求给它一个max_length。这不仅在数据库架构中使用,而且用于验证,我们即将看到。

Field也可能存在一些可选参数,本例中,我们为votes设置了default值为0。

最后,注意一个关联的定义,使用ForeignKey。它告诉Django每个Choice都与一个Question关联。Django支持所有常见的数据库关联:多对一,多对多,一对一。

激活模型

那个小的模型代码给了Django很多信息。有个它,Django可以:

  • 为这个应用(app)创建数据库(CREATE TABLE语句);
  • 创建用于访问QuestionChoice的数据库访问API。

但是,首先我们需要告诉我们的项目,polls应用已安装。

提示:Django的应用是“可插拔”的:你可以将一个app使用在多个项目中,也可以发布你的apps,因为它们并不予给定的Django安装绑定!

来将应用包含到我们的项目中,我们需要在INSTALLED_APPS配置中添加对其配置类的引用。本例的配置类即polls/apps.py文件中的PollsConfig类,所以它的引用路径为"polls.apps.PollsConfig"。编辑mysite/settings.py文件,添加该路径到INSTALLED_APPS配置中。

 # mysite/settings.py

 INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls.apps.PollsConfig',
]

(简单写法,可以直接添加应用名即"polls",因为配置类PollsConfig中定义了"name='polls'")

现在Django知道已包含了polls应用。让我们运行另一个命令:

$ python manage.py makemigrations polls

你可以看到类似下面的内容:

Migrations for 'polls':
polls/migrations/0001_initial.py:
- Create model Choice
- Create model Question
- Add field question to choice

通过运行makemigrations,你告诉Django,你已经对模型进行了一些修改(在这种情况下,你已经创建了新的模型),并希望将这些修改存储为一个迁移(migration)

Migration(迁移)是“Django如何修改你的模型(以及数据库结构)” --它们只是磁盘上的文件。如果你喜欢,可以阅读新模型的迁移,即文件polls/migrations/0001_initial.py。不要担心,Django创建该文件时你不需要去一一阅读,但是它们被设计成可编辑的,你可以手动调整Django修改数据的行为。

有一个命令会运行你的migration并自动管理你的数据库结构 -- 调用migrate命令,稍后介绍该命令。首先,让我们来看看migration会运行哪些SQL语句。sqlmagrate命令接受应用名和migration名称,并返回SQL语句:

$ python manage.py sqlmigrate polls 0001

您应该看到类似于以下内容(我们已经将内容重新格式化的更为易读):

BEGIN;
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
"id" serial NOT NULL PRIMARY KEY,
"choice_text" varchar(200) NOT NULL,
"votes" integer NOT NULL
);
--
-- Create model Question
--
CREATE TABLE "polls_question" (
"id" serial NOT NULL PRIMARY KEY,
"question_text" varchar(200) NOT NULL,
"pub_date" timestamp with time zone NOT NULL
);
--
-- Add field question to choice
--
ALTER TABLE "polls_choice" ADD COLUMN "question_id" integer NOT NULL;
ALTER TABLE "polls_choice" ALTER COLUMN "question_id" DROP DEFAULT;
CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id");
ALTER TABLE "polls_choice"
ADD CONSTRAINT "polls_choice_question_id_246c99a640fbbd72_fk_polls_question_id"
FOREIGN KEY ("question_id")
REFERENCES "polls_question" ("id")
DEFERRABLE INITIALLY DEFERRED; COMMIT;

请注意以下事项:

  • 确切的输出内容将取决于你使用的数据库。上面例子由PostgreSQL生成。(这个文档有坑啊,不是说好的用SQLite吗)。
  • 表名是结合应用名称和小写的model名称(question和choice)自动生成的。(你可以重写这个行为)
  • 主键(ID)将自动添加。如果你在编写model的时候已经添加了主键,就不会自动生成主键ID了。(这个也可以重写)
  • 按照管理,Django会追加"_id"给外键字段名。(你猜我要说什么?是的,这个还是可以重写)
  • 外键关联由FOREIGN KEY显式声明。不要担心DEFERRABLE部分;它只是为了告诉PostgreSQL不要在事务结束前执行外键。
  • 它会适应你使用的数据库,所以数据库的一些特殊字段类型(例如auto_increment--MySQL, serial -- PostgreSQL, integer primary key autoincrement -- SQLite)会自动为你处理。同样适用于对字段名的引用,例如使用双引号或者单引号。
  • sqlmigrate命令实际上不会在数据库上运行migration命令,它只是将Django认为需要执行的SQL语句打印到屏幕上,以便你能看到。这对于检查Django将要执行的操作非常有用 or if you have database administrators who require SQL scripts for changes.(这一句不太懂,先上原文)

如果你有兴趣,可以执行python manage.py check;它会检查项目中的所有问题,而不会执行迁移(migration)或创建数据库。

现在,再次执行migrate,在你的数据库中创建这些模型(model)的表:

$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK

migrate命令使用所有未执行的migration(Django会调用django_migrations跟踪哪个申请使用数据库中的特殊表)并根据数据库运行它们 -- 本质上,将你对模型(model)做的修改同步到数据库的结构中。

Migration非常强大,在开发项目的过程中,使你可以随着时间的推移来修改模型,而不需要删除数据库或表再创建一个新的 -- 它专门用来实时更新数据库,而不会丢失数据。我们将在本教程的后续部分中更深入地介绍它们,但是现在,请记住进行模型更改的三步指南:

  • 修改你的模型(在models.py文件中)
  • 执行python manage.py makemigrations 为这些修改创建迁移
  • 执行 python manage.py migerate 将这些修改应用到数据库中。

将创建和应用migration分为两个命令的原因是你将提交migration到版本控制系统并发送到你的应用;它们不仅可以使您的开发更容易,而且还可以被其他开发人员和在生产中使用。

阅读django-admin documentation了解有关manage.py实用程序可执行操作得当详细信息。

使用API

现在,让我们进入交互式的python shell,并使用Django提供的免费API。要调用Python shell,请使用以下命令:

$ python manage.py shell

我们使用这个,而不是简单的输入"python",因为manage.py设置了DJANGO_SETTING_MODULE环境变量,它告诉Django mysite/settings.py文件的python导入路径。

一旦你进入shell,请探索database API:

>>> from polls.models import Question, Choice   # 导入我们刚写的模型

# 系统中还没有“问题”
>>> Question.objects.all()
<QuerySet []> # 创建一个新“问题”
# 配置文件中默认启动对时区的支持, 所以Django需要提供一个tzinfo的日期给pub_date.使用timezone.now()
# 而不是datetime.datetime.now()
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now()) # 将对象保存到数据库中。你必须显式调用save()
>>> q.save() # 现在它有一个ID,注意,你可能说是‘1L’而不是‘1’,这取决于你使用的数据库。这意味着你的数据库后端更喜欢返回
# 整数作为Python的长整型对象。
>>> q.id
1 # 通过Python属性访问模型字段值.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>) # 通过更改属性来更改值,然后调用save().
>>> q.question_text = "What's up?"
>>> q.save() # oobjects.all()显示数据库中的所有问题.
>>> Question.objects.all()
<QuerySet [<Question: Question object>]>

等一下,<Question: Question object>是对该对象完全无毛用的表示。让我们通过编辑Question模型(在polls/models.py文件中),并在QuestionChoice中添加__str__()方法:

 # polls/models.py

 from django.db import models
from django.utils.encoding import python_2_unicode_compatible @python_2_unicode_compatible # only if you need to support Python 2
class Question(models.Model):
# ...
def __str__(self):
return self.question_text @python_2_unicode_compatible # only if you need to support Python 2
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text

__str__()方法对模型非常重要,这不仅在处理交互式提示时方便您使用,还因为Django自动生成的admin中使用了对象的表示。

注意这些是普通的Python方法。我们添加一个自定义的方法,只是为了演示:

# polls/models.py

import datetime

from django.db import models
from django.utils import timezone class Question(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

注意 import datettimefrom django.utils import timezone,它们分别参考Python标准库的datetime模块和Django中django.utils.timezone的时区关联工具。如果您不熟悉Python中的时区处理,您可以在时区支持文档中了解更多信息。

保存这些更改并重新启动一个新的Python交互式shell :python manage.py shell

>>> from polls.models import Question, Choice

# Make sure our __str__() addition worked.
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]> # Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]> # Get the question that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?> # Request an ID that doesn't exist, this will raise an exception.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist. # Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?> # Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True # Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1) # Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
<QuerySet []> # Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0) # Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?> # And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3 # The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]> # Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

有关模型关系的更多信息,请参阅访问相关对象。有关如何使用双下划线通过API执行字段查找的更多信息,请参阅字段查找。有关数据库API的完整详细信息,请参阅我们的数据库API参考

本人写这篇翻译是英语实在吃力,阅读原文档的时候很费劲,回看下内容更麻烦,所以想着一边看以便翻译出来,最后发现。。效率好低呀,这点东西竟然写了十几个小时,对本人英语水平默哀三分钟。。。

所以我只写了这么断章的一篇,不过我发现了一个不错的博客,这位大神已经把入门的部分都翻译出来了,所以我就没有然后了

大神链接:“全能”选手—Django 1.10文档中文版

Django入门教程(二)的更多相关文章

  1. 无废话ExtJs 入门教程二十一[继承:Extend]

    无废话ExtJs 入门教程二十一[继承:Extend] extjs技术交流,欢迎加群(201926085) 在开发中,我们在使用视图组件时,经常要设置宽度,高度,标题等属性.而这些属性可以通过“继承” ...

  2. 无废话ExtJs 入门教程二十[数据交互:AJAX]

    无废话ExtJs 入门教程二十[数据交互:AJAX] extjs技术交流,欢迎加群(521711109) 1.代码如下: 1 <!DOCTYPE html PUBLIC "-//W3C ...

  3. 无废话ExtJs 入门教程二[Hello World]

    无废话ExtJs 入门教程二[Hello World] extjs技术交流,欢迎加群(201926085) 我们在学校里学习任何一门语言都是从"Hello World"开始,这里我 ...

  4. 【django入门教程】Django的安装和入门

    很多初学django的朋友,都不知道如何安装django开发以及django的入门,今天小编就给大家讲讲django入门教程. 注明:python版本为3.3.1.Django版本为1.5.1,操作系 ...

  5. mongodb入门教程二

    title: mongodb入门教程二 date: 2016-04-07 10:33:02 tags: --- 上一篇文章说了mongodb最基本的东西,这边博文就在深入一点,说一下mongo的一些高 ...

  6. SpringBoot入门教程(二)CentOS部署SpringBoot项目从0到1

    在之前的博文<详解intellij idea搭建SpringBoot>介绍了idea搭建SpringBoot的详细过程, 并在<CentOS安装Tomcat>中介绍了Tomca ...

  7. PySide——Python图形化界面入门教程(二)

    PySide——Python图形化界面入门教程(二) ——交互Widget和布局容器 ——Interactive Widgets and Layout Containers 翻译自:http://py ...

  8. Elasticsearch入门教程(二):Elasticsearch核心概念

    原文:Elasticsearch入门教程(二):Elasticsearch核心概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:ht ...

  9. RabbitMQ入门教程(二):简介和基本概念

    原文:RabbitMQ入门教程(二):简介和基本概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn ...

  10. JasperReports入门教程(二):中文打印

    JasperReports入门教程(二):中文打印 背景 在上一篇中我们介绍了JasperReport的基本入门,也展示了一个报表.但是我们的示例都是使用的英文,如果我们把需要打印的数据改为中文会怎么 ...

随机推荐

  1. 【1414软工助教】团队作业3——需求改进&系统设计 得分榜

    题目 团队作业3--需求改进&系统设计 作业提交情况情况 本次作业所有团队都按时提交作业. 往期成绩 个人作业1:四则运算控制台 结对项目1:GUI 个人作业2:案例分析 结对项目2:单元测试 ...

  2. 201521123040《Java程序设计》第8周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 2. 书面作业 本次作业题集集合 1.List中指定元素的删除(题目4-1) 1.1 实验总结 我们每次删除元 ...

  3. 201521123074 《Java程序设计》第8周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 2. 书面作业 本次作业题集集合 Q1.List中指定元素的删除(题目4-1) 1.1 实验总结 用Arrar ...

  4. 201521123013 《Java程序设计》第9周学习总结

    1. 本章学习总结 2. 书面作业 Q1.常用异常题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何避免? 经常出现Class ...

  5. 201521123022 《Java程序设计》 第十一周学习总结

    1.本章学习总结 2.书面作业 本次PTA作业题集多线程 Q1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问 Q1.1 除了使用synchronized修饰方法实现互斥同步访问,还 ...

  6. java课程设计-猜数游戏

    1. 团队名称.团队成员介绍 团队名称:breeze 团队成员 组长:网络1514张朝玮 201521123106 组员:网络1513侯帅军 201521123092 2. 项目git地址 https ...

  7. TCP/IP协议:OSI七层模型、TCP/IP四层模型的对比

    1. OSI七层和TCP/IP四层的关系 1.1 OSI引入了服务.接口.协议.分层的概念,TCP/IP借鉴了OSI的这些概念建立TCP/IP模型. 1.2 OSI先有模型,后有协议,先有标准,后进行 ...

  8. CentOS克隆机器步骤,图文教程

    在上一篇文章中,主要介绍了CentOS的装机步骤,这一篇文章主要介绍如何从一台装好的CentOS克隆出另一台机器,并且配置好网络. 首先被克隆的CentOS需要关机, 右键点击被克隆的CentOS-& ...

  9. 快递鸟顺丰物流api接口对接多种方法整理

    目前很多自营电商平台.ERP系统.仓储系统.快递柜企业,对物流模块数据需求还是比较旺盛的.之前有介绍过简单的接口对接方法,这次给大家整理介绍两种快递数据的获取方法. 接口秘钥可以向顺丰公司申请,或者一 ...

  10. 浅谈JAVA中“增强”类的某个方法的几个中方法!

    一.继承 使用场景:能够控制这个类的构造的时候,才可以使用继承. 优点:简单容易使用, 缺点:耦合性大大的增强,不利于后期的维护,所以对于继承这种方法,谨慎使用.  代码实现:二.装饰者模式 使用场景 ...