标签:
本文是博主翻译的Django1.10版本官方文档的第一部分,如时间充裕,争取一直翻译下去,经验不足,或有错漏,敬请指正。
另外对于公开文档进行翻译的版权问题不是很清楚,如有侵权请联系我!
第一章、Django1.10文档组成结构
1.1 获取帮助
1.2 文档的组织形式
1.3 第一步
1.4 模型层
1.5 视图层
1.6 模板层
1.7 表单
1.8 开发流程
1.9 admin站点
1.10 安全性
1.11 国际化和本地化
1.12 性能和优化
1.13 Python兼容性
1.14 地理框架
1.15 常用WEB应用工具
1.16 其它核心功能
1.17 Django开源项目
第二章、起步
2.1 Django速览
2.1.1 设计你的模型model
2.1.2 安装model
2.1.3 使用API
2.1.4 功能强大的动态admin后台管理界面
2.1.5 设计你的路由系统URLs
2.1.6 编写你的视图views
2.1.7 设计你的模板
2.1.8 总结
2.2 快速安装指南
2.2.1 安装Python
2.2.2 安装Django
2.2.3 安装验证
2.3 第一个Django app,Part 1
2.3.1 创建project
2.3.2 开发服务器development server
2.3.3 创建投票程序(polls app)
2.3.4 编写视图
2.4 第一个Django app,Part 2
2.4.1 数据库安装
2.4.2 创建模型models
2.4.3 激活模型
2.4.4 学会使用API
2.4.5 Django admin站点介绍
获取帮助的方式:
Django有许多文档,一个高层次的概览有助于你快速找到想要的信息:
如果你是Django或程序员新手,那么从这里开始吧!
Django提供了一个抽象的模型层,用于组织和操纵你的WEB应用数据。
Django将封装响应用户请求逻辑和返回数据称为“视图”。在下面的列表中,你能找到所有和视图相关的内容:
模板层提供一种人性化的语法,用于渲染展示给用户的内容,主要内容包括下列:
Django 提供了一个内容丰富的框架可便利地创建表单及操作表单数据。
学习不同的组件和工具,帮助你开发和测试Django应用。
在这里,你可以找到Django中最受欢迎的功能模块——admin站点的一切:
开发 Web 应用时安全是最重要一个的主题,Django 提供了多重保护工具和机制:
Django 提供了一个强大的国际化和本地化框架,以协助您开发支持多国语言和世界各地区的应用:
有许技术和工具可以帮助你的代码运行得更加高效、快速,占用更少的系统资源。
Django 希望兼容多个不同特性和版本的 Python:
GeoDjango 想要做一个世界级的地理Web框架。 它的目标是尽可能轻松的构建GIS Web 应用和发挥空间数据的能力。
Django 为开发Web应用提供了多种常见的工具:
Django的其它核心功能包括:
下面是Django项目本身的开发进程和如何做出贡献相关:
Django的开发背景是快节奏的新闻编辑室环境,因此它被设计成一个大而全的web框架,能够快速简单的完成任务。本节将快速介绍如何利用Django搭建一个数据库驱动的WEB应用。
它不会有太多的技术细节,只是让你理解Django是如何工作的。
Django提供了ORM,通过它,你能直接使用Python代码来描述你的数据库设计。下面是一个例子:
# mysite/news/models.py
from django.db import models
class Reporter(models.Model):
full_name = models.CharField(max_length=70)
def __str__(self): # __unicode__ on Python 2
return self.full_name
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
def __str__(self): # __unicode__ on Python 2
return self.headline
接下来,进入Django命令行工具,创建数据库表:$ python manage.py migrate
migrate命令查找所有可用的model,如果它还没有在数据库中存在,将根据model创建相应的表。注:也许你需要先执行$ python manage.py makemigrations
命令。
Django为你提供了大量的方便的数据库操作API,无需你编写额外的代码。下面是个例子:
# Import the models we created from our "news" app
>>> from news.models import Reporter, Article
# No reporters are in the system yet.
>>> Reporter.objects.all()
<QuerySet []>
# Create a new Reporter.
>>> r = Reporter(full_name=‘John Smith‘)
# Save the object into the database. You have to call save() explicitly.
>>> r.save()
# Now it has an ID.
>>> r.id
1
# Now the new reporter is in the database.
>>> Reporter.objects.all()
<QuerySet [<Reporter: John Smith>]>
# Fields are represented as attributes on the Python object.
>>> r.full_name
‘John Smith‘
# Django provides a rich database lookup API.
>>> Reporter.objects.get(id=1)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__startswith=‘John‘)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__contains=‘mith‘)
<Reporter: John Smith>
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Reporter matching query does not exist.
# Create an article.
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline=‘Django is cool‘,
... content=‘Yeah.‘, reporter=r)
>>> a.save()
# Now the article is in the database.
>>> Article.objects.all()
<QuerySet [<Article: Django is cool>]>
# Article objects get API access to related Reporter objects.
>>> r = a.reporter
>>> r.full_name
‘John Smith‘
# And vice versa: Reporter objects get API access to Article objects.
>>> r.article_set.all()
<QuerySet [<Article: Django is cool>]>
# The API follows relationships as far as you need, performing efficient
# JOINs for you behind the scenes.
# This finds all articles by a reporter whose name starts with "John".
>>> Article.objects.filter(reporter__full_name__startswith=‘John‘)
<QuerySet [<Article: Django is cool>]>
# Change an object by altering its attributes and calling save().
>>> r.full_name = ‘Billy Goat‘
>>> r.save()
# Delete an object with delete().
>>> r.delete()
Django包含一个功能强大的admin后台管理模块,使用方便,要素齐全。有助于你快速开发。你只需要在下面两个文件中写几句短短的代码:
mysite/news/models.py
from django.db import models
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
mysite/news/admin.py
from django.contrib import admin
from . import models
admin.site.register(models.Article)
Django主张干净、优雅的路由设计,不建议在路由中出现类似.php或.asp之类的字眼。
路由都写在URLconf文件中,它建立起URL匹配模式和python毁掉函数之间的映射,起到了解耦的作用。下面是一个例子:
mysite/news/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r‘^articles/([0-9]{4})/$‘, views.year_archive),
url(r‘^articles/([0-9]{4})/([0-9]{2})/$‘, views.month_archive),
url(r‘^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$‘, views.article_detail),
]
Django通过正则表达式,分析访问请求的url地址,匹配相应的views,调用对应的函数。
每一个视图都必须做下面两件事情之一:返回一个包含请求页面数据的HttoResponse对象或者弹出一个类似404页面的异常。
通常,视图通过参数获取数据,并利用它们渲染加载的模板。下面是一个例子:
mysite/news/views.py
from django.shortcuts import render
from .models import Article
def year_archive(request, year):
a_list = Article.objects.filter(pub_date__year=year)
context = {‘year‘: year, ‘article_list‘: a_list}
return render(request, ‘news/year_archive.html‘, context)
Django有一个模板查找路径,在settings文件中,你可以指定路径列表,Django自动按顺序在列表中查找你调用的模板。一个模板看起来是下面这样的:
mysite/news/templates/news/year_archive.html
{% extends "base.html" %}
{% block title %}Articles for {{ year }}{% endblock %}
{% block content %}
<h1>Articles for {{ year }}</h1>
{% for article in article_list %}
<p>{{ article.headline }}</p>
<p>By {{ article.reporter.full_name }}</p>
<p>Published {{ article.pub_date|date:"F j, Y" }}</p>
{% endfor %}
{% endblock %}
Django使用自己的模板渲染语法,Jinja2就是参考它设计出来的。双大括号包含起来的是变量,它将被具体的值替换。圆点不但可以用来查询属性,也可以用来调用字典键值,列表索引和调用函数。
Django具有模板继承、导入和加载的概念,分别使用extend、include和load语法。下面是一个基础模板大概的样子:
mysite/templates/base.html
{% load static %}
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<img src="{% static "images/sitelogo.png" %}" alt="Logo" />
{% block content %}{% endblock %}
</body>
</html>
子模板继承母模板的内容,并加入自己独有的部分。通过更换母版,可以快速的修改整改站点的外观和样式。
Django为你提供了大量的模块和组件,包括模板系统、模型系统、视图系统以及其他一些通用组件和专用组件。他们之间都是独立的,同时也是可选的,你完全可以使用自己的模板、模型、视图。但是,Django给你提供的是一个集成度高的高效率整体框架,如果你自己的水平不是很高,那建议还是使用Django提供的吧。
在第三章的第一节有详细的安装指南,这里只是一个简单的安装向导,用于快速搭建环境进入下面的章节。
Django与python版本的对应关系。
Django version | Python versions |
---|---|
1.8 | 2.7, 3.2 (until the end of 2016), 3.3, 3.4, 3.5 |
1.9, 1.10 | 2.7, 3.4, 3.5 |
1.11 | 2.7, 3.4, 3.5, 3.6 |
2.0 | 3.5+ |
请前往Python官网下载并安装python。 另外,python和Django自带轻量级数据库SQLite3,因此,在学习阶段你无需安装并配置其他的数据库。
如果你是通过升级的方式安装Django,那么你需要先卸载旧的版本,具体查看3.1.4节。
你可以通过下面的3种方法安装Django:
这里,请前往Django官网下载最新版本或通过pip3 install django进行安装。
进入python环境,输入下列命令,注意版本号和你新安装的一致:
>>> import django
>>> print(django.get_version())
1.10
或者使用命令$ python -m django --version
查看版本号。
下面,我们将进入官方文档提供的编写第一个Django app教程!
在这个例子中,我们将编写一个问卷调查网站,它包含下面两部分:
本教程使用Django 1.10 及Python 3.4以上版本!
进入你指定的某个目录,运行下面的命令:$ django-admin startproject mysite
这将在目录下生成一个mysite目录,也就是你的这个Django项目的根目录。它包含了一系列自动生成的目录和文件,具备各自专有的用途。注意:在给项目命名的时候必须避开Django和Python的保留关键字,比如“django”,“test”等,否则会引起冲突和莫名的错误。对于mysite的放置位置,不建议放在传统的/var/wwww目录下,它会具有一定的数据暴露危险,因此Django建议你将项目文件放在例如/home/mycode类似的位置。
一个新建立的项目结构大概如下:
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
详细解释:
进入mystie目录,输入下面的命令:$ python manage.py runserver
你会看到下面的提示:
Performing system checks...
System check identified no issues (0 silenced).
You have unapplied migrations; your app may not work properly until they are applied.
Run `python manage.py migrate‘ to apply them.
September 07, 2016 - 15:50:53
Django version 1.10, using settings `mysite.settings‘
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Django提供了一个用于开发的web服务器,使你无需配置一个类似Ngnix的线上服务器,就能让站点运行起来。但你也不要将开发服务器用于生产环境,它只是一个简易的测试服务器。
现在,在浏览器访问http://127.0.0.1:8000/,你将看到Django的欢迎阴面,一切OK!
django开发服务器(以后省略)默认运行在内部的8000端口,如果你想指定,请在命令中显示给出,例如:$ python manage.py runserver 0.0.0.0:8000
上面:Django将运行在8000端口,整个子网内都将可以访问,而不是本机。
注意: Django的开发服务器具有自动重载功能,当你的代码有修改,每隔一段时间服务器将自动更新。但是,有一些例如增加文件的动作,不会触发服务器重载,这时就需要你自己手动重启。
app与project的区别:
app的存放位置可以是任何地点,但是通常我们将它们都放在与manage.py同级目录下,这样方便导入文件。
进入mysite目录,确保与manage.py文件处于同一级,输入下述命令:$ python manage.py startapp polls
系统会自动生成 polls目录,其结构如下:
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
在polls/views.py文件中,输入下列代码:
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You‘re at the polls index.")
为了调用该视图,我们还需要编写urlconf。现在,在polls目录中新建一个文件,名字为urls.py,在其中输入代码如下:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r‘^$‘, views.index, name=‘index‘),
]
下一步是让项目的主urls文件指向我们建立的polls这个app独有的urls文件,你需要先导入include模块,打开mysite/urls.py文件,代码如下:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r‘^polls/‘, include(‘polls.urls‘)),
url(r‘^admin/‘, admin.site.urls),
]
include语法相当于二级路由策略,它将接收到的url地址去除了它前面的正则表达式,将剩下的字符串传递给下一级路由进行判断。在路由的章节,有更加详细的用法指导。
include的背后是一种即插即用的思想。项目根路由不关心具体app的路由策略,只管往指定的二级路由转发,实现了解耦的特性。app所属的二级路由可以根据自己的需要随意编写,不会和其它的app路由发生冲突。app目录可以放置在任何位置,而不用修改路由。这是软件设计里很常见的一种模式。
建议:除了admin路由外,你应该尽量给每个app设计自己独立的二级路由。
好了,路由也搭建成功,下面我们启动服务器,然后在浏览器中访问地址http://localhost:8000/polls/
。一切正常的话,你将看到“Hello, world. You’re at the polls index.”
url()函数可以传递4个参数,其中2个是必须的:regex和view,以及2个可选的参数:kwargs和name。下面是具体的解释:
regex:
regex是正则表达式的通用缩写,它是一种匹配字符串或url地址的语法。Django拿着用户请求的url地址,在urls.py文件中对urlpatterns列表中的每一项条目从头开始进行逐一对比,一旦遇到匹配项,立即执行该条目映射的视图函数或二级路由,其后的条目将不再继续匹配。因此,url路由的编写顺序至关重要!
需要注意的是,regex不会去匹配GET或POST参数或域名,例如对于https://www.example.com/myapp/,regex只尝试匹配myapp/。对于https://www.example.com/myapp/?page=3,regex也只尝试匹配myapp/。
如果你想深入研究正则表达式,可以读一些相关的书籍或专论,但是在Django的实践中,你不需要多高深的正则表达式知识。
性能注释:正则表达式会进行预先编译当URLconf模块加载的时候,因此它的匹配搜索速度非常快,你通常感觉不到。
view:
当正则表达式匹配到某个条目时,自动将封装的HttpRequest对象作为第一个参数,正则表达式“捕获”到的值作为第二个参数,传递给该条目指定的视图。如果是简单捕获,那么捕获值将作为一个位置参数进行传递,如果是命名捕获,那么将作为关键字参数进行传递。
kwargs:
任意数量的关键字参数可以作为一个字典传递给目标视图。
name:
对你的URL进行命名,可以让你能够在Django的任意处,尤其是模板内显式地引用它。相当于给URL取了个全局变量名,你只需要修改这个全局变量的值,在整个Django中引用它的地方也将同样获得改变。这是极为古老、朴素和有用的设计思想,而且这种思想无处不在。
接着上一部分,本节将讲述如何安装数据库,编写第一个模型以及简要的介绍下Django自动生成的admin站点。
打开mysite/settings.py配置文件。Django默认使用内置的SQLite数据库。当然,如果你是在创建一个实际的项目,请使用类似MySql的生产用数据库,避免以后面临数据库切换的头疼。
如果你想使用别的数据库,请先安装相应的数据库模块,并将settings文件中DATABASES ’default’的键值进行相应的修改,用于连接你的数据库。其中:
ENGINE(引擎):可以是’django.db.backends.sqlite3’或者’django.db.backends.postgresql’,’django.db.backends.mysql’, or ’django.db.backends.oracle’,当然其它的也行。
NAME(名称):数据库的名字。如果你使用的是默认的SQLite,那么数据库将作为一个文件将存放在你的本地机器内,NAME应该是这个文件的完整绝对路径,包括文件名。设置中的默认值os.path.join(BASE_DIR, ’db.sqlite3’),将把该文件储存在你的项目目录下。
如果你不是使用默认的SQLite数据库,那么一些诸如USER,PASSWORD和HOST的参数必须手动指定!更多细节参考后续的数据库章节。
注意:
在修改settings文件时,请顺便将TIME_ZONE设置为你所在的时区。
同时,请注意settings文件中顶部的INSTALLED_APPS设置项。它保存了所有的在当前项目中被激活的Django应用。你必须将你自定义的app注册在这里。每个应用可以被多个项目使用,而且你可以打包和分发给其他人在他们的项目中使用。
默认情况,INSTALLED_APPS中会自动包含下列条目,它们都是Django自动生成的:
上面的每个应用都至少需要使用一个数据库表,所以在使用它们之前我们需要在数据库中创建这些表。使用这个命令:$ python manage.py migrate。
migrate命令将遍历INSTALLED_APPS设置中的所有项目,在数据库中创建对应的表,并打印出每一条动作信息。如果你感兴趣,可以在你的数据库命令行下输入:\dt
(PostgreSQL), SHOW TABLES; (MySQL), 或 .schema (SQLite) 来列出 Django 所创建的表。
提示:对于极简主义者,你完全可以在INSTALLED_APPS内注释掉任何或者全部的Django提供的通用应用。这样,migrate也不会再创建对应的数据表。
Django通过自定义python类的形式来定义具体的模型,每个模型代表数据库中的一张表,每个类的实例代表数据表中的一行数据,类中的每个变量代表数据表中的一列字段。Django通过ORM对数据库进行操作,奉行代码优先的理念,将python程序员和数据库管理员进行分工解耦。
在这个简单的投票应用中,我们将创建两个模型:Question和Choice。Question包含一个问题和一个发布日期。Choice包含两个字段:选择的文本和投票计数。每一条Choice都关联到一条Question。这些都是由python的类来体现,编写的全是python的代码,不接触任何sql语句。现在,编辑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中使用一个可选的第一位置参数用于提供一个人类可读的字段名,让你的模型更友好,更易读,并且将被作为文档的一部分来增强代码的可读性。在本例中,仅定义了一个符合人类习惯的字段名Question.pub_date。对于模型中的其他字段,机器名称就已经足够我们认读了。
一些Field类必须提供某些特定的参数。例如CharField需要你指定max_length。这不仅是数据库结构的需要,同样也用于我们后面会谈到的数据验证功能。
有必填参数,当然就会有可选参数,比如在votes里我们将其默认值设为0.
最后请注意,我们使用ForeignKey定义了一个外键关系。它告诉Django,每一个Choice关联到一个对应的Question。Django支持通用的数据关系:一对一,多对一和多对多。
上面的代码看着有点少,但却给予Django大量的信息,据此,Django会做下面两件事:
但是,首先,我们得先告诉项目,我们已经安装了投票应用。
Django思想:应用是“可插拔的”:你可以在多个项目使用一个应用,你也可以分发应用,它们不会被捆绑到一个给定的 Django 项目中。
要将应用添加到项目中,需要在INSTALLED_APPS设置中增加指向该应用的配置文件的链接。对于本例的投票应用,它的配置类文件是polls/apps.py,路径格式为’polls.apps.PollsConfig’。我们需要在INSTALLED_APPS中,将该路径添加进去。它看起来是这样的:
mysite/settings.py
INSTALLED_APPS = [
‘polls.apps.PollsConfig‘,
‘django.contrib.admin‘,
‘django.contrib.auth‘,
‘django.contrib.contenttypes‘,
‘django.contrib.sessions‘,
‘django.contrib.messages‘,
‘django.contrib.staticfiles‘,
]
现在Django已经知道你的投票应用的存在了,并把它加入了大家庭。我们再运行下一个命令:$ python manage.py makemigrations polls。你会看到类似下面的提示:
Migrations for ‘polls‘:
polls/migrations/0001_initial.py:
- Create model Choice
- Create model Question
- Add field question to choice
通过运行migrations命令,相当于告诉Django你对你的模型有改动,并且你想把这些改动保存为一个“迁移”。
migrations是Django保存模型修改记录的文件,它们是保存在磁盘上的文件。在例子中,它就是polls/migrations/0001_initial.py文件,你可以打开它看看,里面保存的都是可编辑的内容,方便你随时手动修改。
接下来有一个叫做migrate的命令将对数据库执行真正的迁移动作,下面我们就要介绍它。但是,在此之前,让我们先看看在migration的时候实际试行的SQL语句是什么。有一个叫做sqlmigrate的 命令可以展示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;
请注意:
如果你感兴趣,也可以运行python manage.py check命令,它将检查项目中所有没有进行迁移或者链接数据库的错误。
现在,我们可以运行migrate命令,在数据库中进行真正的表操作了。
$ 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命令对所有还未实施的迁移记录进行操作,本质上就是将你对模型的修改体现到数据库中具体的表上面。Django通过一张叫做django_migrations的表,记录并跟踪已经实施的migrate动作,通过对比获得哪些migrations尚未提交。
migrations的功能非常强大,允许你随时修改你的模型,而不需要删除或者新建你的数据库或数据表,在不丢失数据的同时,实时动态更新数据库。我们将在后面的章节对此进行深入的阐述,但是现在,我们只需要记住修改模型时的操作分三步:
之所以要将创建和实施迁移的动作分成两个命令两步走是因为你也许要通过版本控制系统(例如github,svn)提交你的项目代码,如果没有一个中间过程的保存文件(migrations),那么github如何知道以及记录、同步、实施你所进行过的模型修改动作呢?毕竟,github不和数据库直接打交道,也没法和你本地的数据库打交道。但是分开之后,你只需要将你的migration文件(例如上面的0001)上传到github,它就会知道一切。
下面,让我们进入python交互环境,学习使用Django提供的数据库访问API。要进入python的shell,请输入命令:
$ python manage.py shell
相比较直接输入“python”命令的方式进入python环境,调用manage.py参数能将DJANGO_SETTINGS_MODULE环境变量导入,它将自动按照mysite/settings.py中的设置,配置好你的python shell环境,这样,你就可以导入和调用任何你项目内的模块了。
或者你也可以这样,先进入一个纯净的python shell环境,然后启动Django,具体如下:
>>> import django
>>> django.setup()
如果上述操作出现AttributeError异常,有可能是你正在使用一个和当前教程不匹配的Django版本。解决办法是学习较低版本的教程或更换更新版本的Django。
不管是哪种方式,你最终都是让python命令能够找到正确的模块地址,得到正确的导入。
当你进入shell后,尝试一下下面的API吧:
>>> from polls.models import Question, Choice # 导入我们写的模型类
# 现在系统内还没有questions
>>> Question.objects.all()
<QuerySet []>
# 创建一个新的question
# Django推荐使用timezone.now()代替python内置的datetime.datetime.now()
from django.utils import timezone
>>> q = Question(question_text="What‘s new?", pub_date=timezone.now())
# 你必须显式的调用save()方法,才能将对象保存到数据库内
>>> q.save()
# 默认情况,你会自动获得一个自增的名为id的主键
>>> 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()
# objects.all() 用于查询数据库内的所有questions
>>> Question.objects.all()
<QuerySet [<Question: Question object>]>
这里等一下:上面的<Question: Question object>是一个不可读的内容展示,你无法从中获得任何直观的信息,为此我们需要一点小技巧,让Django在打印对象时显示一些我们指定的信息。返回polls/models.py文件,修改一下question和Choice这两个类,代码如下:
polls/models.py
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible # 当你想支持python2版本的时候才需要这个装饰器
class Question(models.Model):
# ...
def __str__(self): # 在python2版本中使用的是__unique__
return self.question_text
@python_2_unicode_compatible
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text
这个技巧不但对你打印对象时很有帮助,在你使用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)
请注意上面分别导入了两个关于时间的模块,一个是python内置的datetime一个是Django工具包提供的timezone。
保存修改后,我们重新启动一个新的python shell,再来看看其他的API:
>>> from polls.models import Question, Choice
# 先看看__str__()的效果,直观多了吧?
>>> Question.objects.all()
<QuerySet [<Question: What‘s up?>]>
# Django提供了大量的关键字参数查询API
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What‘s up?>]>
>>> Question.objects.filter(question_text__startswith=‘What‘)
<QuerySet [<Question: What‘s up?>]>
# 获取今年发布的问卷
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What‘s up?>
# 查询一个不存在的ID,会弹出异常
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.
# Django为主键查询提供了一个缩写:pk。下面的语句和Question.objects.get(id=1)效果一样.
>>> Question.objects.get(pk=1)
<Question: What‘s up?>
# 看看我们自定义的方法用起来怎么样
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True
# 让我们试试外键查询
>>> q = Question.objects.get(pk=1)
# 显示所有与q对象有关系的choice集合,目前是空的,还没有任何关联对象。
>>> q.choice_set.all()
<QuerySet []>
# 创建3个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对象可通过API访问和他们关联的Question对象
>>> c.question
<Question: What‘s up?>
# 同样的,Question对象也可通过API访问关联的Choice对象
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3
# API会自动进行连表操作,通过双下划线分割关系对象。连表操作可以无限多级,一层一层的连接。
# 下面是查询所有的Choices,它所对应的Question的发布日期是今年。(重用了上面的current_year结果)
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
# 使用delete方法删除对象
>>> c = q.choice_set.filter(choice_text__startswith=‘Just hacking‘)
>>> c.delete()
获取更多关于模型关系的信息,请查看6.15.4章节。更多的数据库API和如何使用双下划线进行查询,请看3.2.2章节。
设计理念:为你的团队或客户编写用于增加、修改和删除内容的admin站点是一件非常乏味的工作并且没有多少创造性。因此,Django自动地为你通过模型构造了一个admin站点。这个站点只给站点管理员使用,并不对大众开放。
首先,通过下面的命令,创建一个可以登录admin站点的用户:
$ python manage.py createsuperuser
输入用户名:
Username: admin
输入邮箱地址:
Email address: admin@example.com
输入密码:
Password: **********
Password (again): *********
Superuser created successfully.
注意:Django1.10版本后,超级用户的密码强制要求具备一定的复杂性,不能再偷懒了。
服务器启动后,在浏览器访问http://127.0.0.1:8000/admin/。你就能看到admin的登陆界面了:
利用刚才建立的admin账户,登陆站点,你将看到如下的界面:
当前已经有两个可编辑的内容:groups和users。它们是django.contrib.auth模块提供的身份认证框架。
现在你还无法看到你的投票应用,必须先在admin中进行注册,告诉admin站点,请将poll的模型加入站点内,接受站点的管理。
打开polls/admin.py文件,加入下面的内容:
polls/admin.py
from django.contrib import admin
from .models import Question
admin.site.register(Question)
注册question模型后,刷新admin页面就能看到Question栏目了。
点击“Questions”,进入questions的修改列表页面。这个页面会显示所有的数据库内的questions对象,你可以在这里对它们进行修改。看到下面的“What’s up?”了么?它就是我们先前创建的一个question,并且通过__str__方法的帮助,显示了较为直观的信息,而不是一个冷冰冰的对象类型名称。
下面,点击What’s up?进入编辑界面:
这里需要注意的是:
在页面的底部,则是一些可选项按钮:
如果“Date published”字段的值和你在前面教程创建它的时候不一致,可能是你没有正确的配置TIME_ZONE,在国内,通常是8个小时的时间差别。修改TIME_ZONE配置并重新加载页面,就能显示正确的时间了。
在页面的右上角,点击“History”按钮,你会看到你对当前对象的所有修改操作都在这里有记录,包括修改时间和操作人,如下图所示:
到此,你对模型API和admin站点有了一定的熟悉,可以进入下一阶段的教程了。
觉得还行就点赞支持一下吧!
标签:
原文地址:http://www.cnblogs.com/Leo_wl/p/5918147.html