目录
编写第一个Django应用程序,第二部分
数据库设置
创建模型(Model)
激活模型
使用API
Django Admin 简介
创建管理员用户
启动开发服务器
进入管理站点
将投票应用程序加入管理站点
探索管理功能
编写第一个Django应用程序,第二部分
本文接上篇文章的第一部分。本部分将会进行数据库设置,创建我们的第一个模型(Model),并快速了解Django自动生成的管理站点。
数据库设置
现在,我们打开 mysite/settings.py,它是一个普通的Python模块,Django设置的模块级变量都在该模块中进行设置。
默认情况下,Django使用的数据库是SQLite。如果你是数据库新手或者只是感兴趣尝试一下Django,那么这是最简单的选择,这样也不需要更改关于数据库的任何配置。SQLite包含在Python中,所以我们不需要安装额外的内容来支持SQLite数据库。当然,你也可以选择使用其它的数据库,例如PostgreSQL、MySQL、Oracle等,如果是实际项目的话,推荐使用这些数据库。我这里使用的数据库是MySQL数据库,和官网不一样,官网教程使用的数据库是PostgreSQL,你也可以选择你现在使用的数据库。
如果使用其它的数据库,需要安装对应数据库的Python支持。比如我使用的是MySQL,我就需要使用下面的命令安装MySQL数据库的相关模块:
pip install mysqlclient
安装完成后,就需要修改数据库的连接设置以匹配当前使用的数据库。数据库连接配置:DATABASES ‘default’。下面我们来看一下关于数据库连接的配置。
- ENGINE – 配置数据库引擎。常见的有:’django.db.backends.sqlite3‘,’django.db.backends.postgresql‘,’django.db.backends.mysql‘,’django.db.backends.oracle‘。如果你使用的数据库不在这里面,可以通过查看官方文档获得。
- NAME – 数据库名称。如果使用的是默认的SQLite,那么它指的就是SQLite数据库文件;在这种情况下,NAME应该是该文件完整的绝对路径。默认配置的就是SQLite文件的位置:BASE_DIR / ‘db.sqlite3’。你会发现,我们第一次启动项目后,该文件会自动生成在我们的项目文件夹下。
- 如果不使用SQLite作为数据库,则必须添加其它设置。例如:USER、PASSWORD、HOST等设置。更多的设置请参考官方文档DATABASES。
下面展示一下我使用的MySQL数据库在文件中的配置:
DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'polls','USER': 'root','PASSWORD': '123456','HOST': '127.0.0.1','PORT': '3306'}
}
对于SQLite以外的数据库
如果你使用的是SQLite以外的数据库,请确保在运行项目时已经创建了数据库;还要确保提供的数据库用户具有“创建数据库”权限,因为后面我们会使用Django自动创建数据库表的功能。如果使用的是默认的SQLite数据库,则不需要做什么额外的工作。
数据库设置完成后,接下来我们来更改一下 mysite/settings.py 中关于时区(TIME_ZONE)的设置。因为默认的时区可能和我们实际所在的时区是不一样的,为避免时间上出现错误,我们需要对其进行更改。更改如下所示:
# 语言:简体中文
LANGUAGE_CODE = 'zh-hans'
# 时区:亚洲 上海
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
# 为了保证Django存入MySQL数据库时间差8个小时的问题
USE_TZ = False
这里的设置应该不难看懂。除了对时区进行设置外,我还将项目文字设置成了简体中文,因为Django会生成一些常用的功能,这些功能都有对应的操作界面,这里设置为中文后,界面中的文字也会相应的变为中文。这是关于国际化的设置。
你在 mysite/settings.py 文件中应该还会看到 INSTALLED_APPS 这样一个设置,它是一个列表,里面配置了好多类。它保存的是此Django实例中激活的所有Django应用程序的名称。应用程序可以在多个项目中使用,也可以打包并将它们分发给其他人供其在项目中使用。
默认情况下,INSTALLED_APPS 包含以下应用程序:
- 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/settings.py 文件中的数据库设置以及应用程序中所需要的数据库进行数据库表的创建。在创建数据库表的过程中,命令行会打印出创建数据库表的应用程序和其对应的数据库表。数据库表创建完成后,可以通过相应的数据库客户端查看所创建的表(下图为创建的数据库表)。
极简主义
正如我们上面所说,默认情况下项目会自动包含这些常见的应用程序,但不是每个项目都需要它们。如果不需要它们中的哪个或者哪些,那么你需要在执行 migrate 命令之前将你不需要的应用程序进行删除。
创建模型(Model)
创建Model的作用在这里就不再进行说明了,毕竟关于它的讲解已经很多很完善了。如果你之前使用过Java,那么对它会更熟悉。
在我们的投票应用程序中,我们将创建两个Model:Question(问题)和Choice(选择)。Question有两个属性:问题和发布日期。Choice也有两个属性:选择的文本和投票数。每个Choice都与一个Question相关联。
接下来我们就要用Python类表示这两个Model。我们打开 polls/models.py 文件,在其中编写这两个Python类:
import datetime# Create your models here.
class Question(models.Model):question_text = models.CharField("问题", max_length=200)pub_date = models.DateTimeField("发布日期")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 的子类。每个模型都有很多变量,每个变量代表模型中的一个数据库字段。每个字段都是一个Filed类的实例。例如:CharField是字符字段,DateTimeField是日期时间字段。这告诉Django每个字段保存的数据类型。
这里使用的变量名就是稍后程序生成的对应的数据库表的列名,所以变量名要尽量清楚易懂。Field字段的第一个参数用于设置该字段的名称,该名称会在管理页面中进行展示,如果不设置该参数,默认使用变量名。
有些Field类有必填参数。比如CharField,它要求我们填入max_length参数。该参数不仅用于设置数据库,还用于验证。
Field还有各种可选参数;比如当前代码中我们将votes的default设置为0。
最后,需要注意的是我们使用了关系定义ForeignKey。这告诉Django每个Choice与一个Question相关。Django支持所有常见的数据库关系:多对一、多对多和一对一。
激活模型
这一小段代码为Django提供了大量信息。有了它,Django能够:
- 为此应用程序创建对应的数据库表
- 创建用于访问Question和Choice对象的Python数据库访问API。
但首先我们需要将polls应用程序安装到我们的项目中。
要将应用程序安装到项目中,其实是很简单的,只需要我们将应用程序配置类配置到INSTALLED_APPS中就可以了。polls应用程序的配置类名称为PollConfig,位于polls/apps.py文件中。该类的路径为 ‘polls.apps.PollsConfig‘,所以,更改后的mysite/settings.py文件中的INSTALLED_APPS配置如下所示:
INSTALLED_APPS = ['polls.apps.PollsConfig','django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles',
]
现在Django已经知道该项目包含polls应用程序了。让我们运行另一个命令:
python manage.py makemigrations polls
运行命令后,你应该会看到类似下面的内容:
Migrations for 'polls':polls/migrations/0001_initial.py- Create model Question- Create model Choice
通过运行makemigrations,我们告诉了Django我们已经对模型做了一些更改并且希望将更改进行存储。
我们可以对生成的Django模型(已经数据库模式)进行更改,它们只是硬盘上的一个文件。文件位于polls/migrations/0001_initial.py,如果有必要,你可以手工对它进行调整。
通过运行sqlmigrate命令,我们可以得到应用程序创建数据库表的相关SQL语句。
python manage.py sqlmigrate polls 0001
你会看到类似下面的内容(为了阅读方便,对其进行了格式化):
--
-- Create model Question
--
CREATE TABLE `polls_question` (`id` BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY, `question_text` VARCHAR(200) NOT NULL, `pub_date` DATETIME(6) NOT NULL
);
--
-- Create model Choice
--
CREATE TABLE `polls_choice` (`id` BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY, `choice_text` VARCHAR(200) NOT NULL, `votes` INTEGER NOT NULL, `question_id` BIGINT NOT NULL
);
ALTER TABLE `polls_choice`
ADD CONSTRAINT `polls_choice_question_id_c5b4b260_fk_polls_question_id`FOREIGN KEY (`question_id`)REFERENCES `polls_question` (`id`);
注意事项:
- 具体的SQL语句输出会根据你使用的数据库进行生成。上面生成的示例是为MySQL生成的。
- 表名是通过应用程序名称(polls)和Model名称的小写(question)以“_”连接而成的。
- 主键(id)会自动添加,无需人工干预。
- sqlmigrate命令并不会运行SQL语句,它只是将SQL语句打印到屏幕上,以便我们可以看到Django是怎么做的。它对于检查Django将要执行的数据库操作是非常有用的。
如果你有兴趣,你也可以运行python manage.py check,它会检查项目中的任何问题,而不会对数据库进行任何操作。
现在,我们再次运行migrate以便在数据库中创建polls应用程序所需的数据库表。
python manage.py migrate
migrate命令会获取尚未执行数据库操作的应用程序或者有数据库更改的应用程序,然后将它们执行。
migrate功能非常强大,可以让我们在开发项目时随着时间的推移而更改模型时,无需删除数据库或删除数据库表重新创建,它会实时的更新数据库,而不会丢失数据。
现在我们将更改模型的步骤做一个总结:
- 更改模型(在models.py)。
- 为这些更改运行python manage.py makemigrations,查看生成的SQL语句。
- 如果生成SQL语句无误,则运行python manage.py migrate,以便让更改应用到数据库。
使用API
现在,让我们进入交互式Python shell并使用Django为我们提供的免费API。输入以下命令进入Python shell:
python manage.py shell
我们使用它而不是简单地输入“python”,因为manage.py设置了DJANGO_SETTINGS_MODULE环境变量,mysite/settings.py文件为Django提供了Python的导入路径。
进入shell后,我们来看一些常用的数据库API:
# 导入Question,Choice
>>> from polls.models import Question, Choice
# 查询Question的所有数据
>>> Question.objects.all()
<QuerySet []># 插入一条Question
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())# 保存数据到数据库,我们需要调用对象的 save() 方法
>>> q.save()# 现在 q 已经插入到数据库表中了,已经有了ID
>>> q.id
1# 我们可以通过Python属性访问的方式获取对应模型的字段值
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2024, 1, 29, 20, 50, 30, 853724)# 更改数据只需要更改对应的属性值,然后调用 save() 方法就可以了
>>> q.question_text = "What's up?"
>>> q.save()# objects.all() 显示指定对象的所有数据库数据
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
等一下,]>这样的输出对我们没有一点用处,根本看不出它是什么。为了更改对象的输出,我们需要更改Question(polls/models.py)模型,在里面添加__str__()方法,同样的,我们在Choice中也添加该方法,为了让Choice输出也能看得懂。
from django.db import models
from django.utils import timezone# Create your models here.
class Question(models.Model):# ...def __str__(self):return self.question_textclass Choice(models.Model):# ...def __str__(self):return self.choice_text
__str__()方法是非常重要的,这不仅是方便了我们的查看,而且还因为对象的表示形式在Django自动生成的管理中使用。
我们还向Question模型中添加了一个自定义方法:
import datetimefrom django.db import models
from django.utils import timezone# Create your models here.
class Question(models.Model):# ...def was_published_recently(self):return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
保存这些更改并再次运行新的Python交互式shell:python manage.py shell。
>>> 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?>]># 查询今年的Question
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?># 使用 get() 方法获取指定ID的数据,如果数据不存在,则会抛出一个异常
>>> Question.objects.get(id=2)
Traceback (most recent call last):...
DoesNotExist: Question matching query does not exist.# 根据主键查询数据是最常用的方法,所以Django提供了主键查询的快捷方法
# 下面的语句和 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# 现在给Question添加一些Choice
# Choice添加不是通过Choice对象,而是通过Question对象进行添加,因为Choice和Question有外键关系,Django会通过这种关系将数据添加到数据库
>>> q = Question.objects.get(pk=1)# 通过关键对象set查看Question的Choice
>>> q.choice_set.all()
<QuerySet []># 创建3个Choice
>>> 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: Just hacking again># Choice对象可以API访问其相关的Question对象
>>> c.question
<Question: What's up?># 反之亦然,Question对象同样可以获取其相关的Choice对象
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3# API会根据我们的需要自动跟踪关联关系
# 使用双下划线分隔关系
# 关联层级没有限制,多少都可以
# 查找Question发布日期为今年的所有Choice
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]># 让我们从choices中删除一个。使用 delete() 删除数据
>>> c = q.choice_set.filter(choice_text__startswith="Just hacking")
>>> c.delete()
关于数据库API的完整内容,可以通过官方文档进行查看。
Django Admin 简介
哲学
为员工或客户生成管理网站以添加、更改和删除内容是一项乏味的工作,很多的系统都有类似的功能,不需要太多创造力。因此,Django自动创建了模型的管理界面。
Django是在新闻编辑室环境中编写的,“内容发布者”和“公共站点”之间有非常清晰的分离。站点管理员使用该系统添加新闻报道、事件、体育比分等,并将这些内容显示在公共站点上。Django解决了为站点管理员创建统一界面来编辑内容的问题。
管理界面不应该被网站访问者访问,它只适用于站点管理员。
创建管理员用户
首先,我们需要创建一个可以登录管理站点的用户。执行以下命令:
python manage.py createsuperuser
根据提示输入想要创建的管理员用户名和密码,完成后回车确认即可。
启动开发服务器
Django管理站点默认处于激活状态。让我们启动开发服务器并探索它。启动开发服务器命令:
python manage.py runserver
现在,打开浏览器根据你启动的地址在后面加上”/admin/”,例如:http://localhost:8000/admin。你应该会看到管理员的登录页面:
管理站点将根据我们设置的LANGUAGE_CODE显示相应的文字。例如我们设置的是简体中文,这里就显示简体中文。
进入管理站点
现在我们使用创建的用户名和密码登录管理站点。登录后,你会看到Django管理页面:
你应该会看到用户和组的内容,它们是由Django的django.contrib.auth提供的身份验证框架。
将投票应用程序加入管理站点
细心的你可能已经发现了,我们的投票程序没有出现在管理页面中,那是因为我们没有将其加入到管理页面。
现在我们将投票应用程序加入管理,我们需要告诉管理我们有一个Question对象需要被加入到管理页面中。为此,我们打开polls/admin.py,并编辑如下内容:
from django.contrib import adminfrom .models import Question# Register your models here.
admin.site.register(Question)
探索管理功能
现在我们已经将Question注册到管理站点中了,Django将知道它应该显示在管理页面上:
点击“Question”,我们进入其对应的列表页面。该页面提供对Question的增删改查操作。页面功能是相当清晰的,通过点击查看可以快速了解其提供的功能,这里就不再进行描述。
一点说明:
- 页面表单是通过Question模型自动生成的。
- 不同的模型字段类型对应不同的HTML部件。
欢迎关注我的公众号