开始Django之旅-part2_Django和数据库mysql

上一篇:开始Django之旅-part1_构建你的第一个Django app

前言

假定你已经看了上一篇文章并且完成了任务,在这里,在下将带领你建立数据库,创建你的第一个model,然后快速的了解一下由Django自动生成的admin地址。

建立数据库

现在,打开mysite/settings.py.它是一个带有模块级别变量的Python module(模块),是一个Django设置文件。

默认情况下,该配置文件使用的是SQLite数据库,如果你刚开始接触数据库、或者你仅仅对Django有兴趣,SQLite是一个最容易的选择。SQLite内嵌在Python中,所以你不需要在安装软件啦。然而,当启动你第一个正式的项目时,你可能想要使用一个像PostgreSQL容量可伸缩的数据库,避免在使用Django一段时间之后转换数据库的痛苦。

如果你希望使用另一种数据库,首先安装合适的数据库绑定包,然后更改在DATABASE ‘default’ 下的关键字,去匹配你的数据库的连接设置:

ENGING(任选一个)

  • ’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’),这使得数据库文件存储在项目目录中。

如果你使用其他的数据库,像URSE、PASSWORD和HOST等额外的设置参数必须添加,像这样:(更多配置细节
在这里插入图片描述注意:如果你使用其他的数据库,确保:
1.你已经建立了数据库(create database database_name)
2.确保你所提供的用户有建立数据库的权限,因为后续要用到的测试数据库,是需要自动创建的
3.如果你使用的是SQLite,你不需要提前做任何事,当需要的时候,数据库文件就会自动建好

当你正在编辑mysite/settings.py时,设置TIME_ZONE(默认是America/Chicago,该设置同样在database-default中设置)为你当前的时区(Asia/Hong_Kong)。list of time zones

同样的,注意一下文件顶部的INSTALLED_APPS设置,它包括了所有Django应用的名称,它们会在Django启动的时候激活,Apps可以被用于多个项目。你可以将它们打包,然后发布它们,就可以让别人在他们的项目中使用。
在这里插入图片描述默认情况下,INSTALLED_APPS包含了一下apps,它们和Django一起运行。

  • ‘django.contrib.admin’, 管理员地址,一会你就会用到
  • ‘django.contrib.auth’,一个认证系统
  • ‘django.contrib.contenttypes’,一个内容类型的框架
  • ‘django.contrib.sessions’,一个session框架
  • ‘django.contrib.messages’,一个通信框架
  • ‘django.contrib.staticfiles’,一个管理静态文件的框架

这些apps一般情况下都是默认包含的。

其中一些apps最少用到一个数据库表,所以我们在使用这些apps之前就需要创建数据库表,开始建表:

...\> py manage.py migrate

migrate命令检查了INSTALLED_APPS设置,并根据mysite/settings.py中的数据库设置创建了任何必要的数据库表,这些数据库表伴随着app的转移而转移(我们之后会讲到),你会在cmd看到它的每个移动信息。如果你有兴趣的话,运行你的数据库,查看你的数据库表。

温馨提示:就像我们之前说过的一样,这些默认的app一般都被包含在项目中,如果你不需要他们,在运行migrate之前随便注释掉或删掉。migrate命令只会迁移INSTALLED_APPS中包含的app数据库表。

创建models

现在我们要定义你的models,必要情况下,你的数据库会有一些元数据的设计。

什么是model呢?

一个model是你的数据单一的、确定的真实来源。它包含了必要的数据类型和你存储的数据的行为。Django遵循了DRY原则。目标就是在一个地方确定你的数据模型,然后自动的从那里得到一些东西。

model包含了migrations(迁移数据库表),比如,migrations完全的来源于你的models文件,model本质上就是一个记录,Django可以通过它去更新你的数据库体系,来匹配当前的models。

在我们的投票app中,我们会创建两个models:Question和Choice。一个Question有一个question和一个发布日期,一个Choice有两个字段:选择的文本和投票记数。每个Choice都和Question关联。

这些概念都是通过Python类表现出来的。现在编辑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)

在这里,每一个model都被 django.db.models.Model的子类表示,每一个model都有许多变量,他们代表在model中的数据库字段。

每一个字段都被一个Field类实例所表示,比如,CharField表示字符字段,DateTimeField表示 datetimes字段。这些告诉Django存储每个数据为何种类型。

每一个Field实例(question_text,pub_date)的名字并不是字段名字,知识机器友好的命名格式。你会在你的Python代码中使用它们的值,并且你的数据库会使用它作为列名。

你可以在Field类中的第一个可选参数中设置一个读得懂的名字,这被应用到Django的一部分,用来自我检查,它也是作为一个提示文档的备份。如果这个字段没有被提供,Django会使用机器可读的命名。在这个例子中,我们只定义了Question.pub_date的人可读的命名,对于其他的字段,机器可读的命名已经足够作为人可读的命名了。

一些字段类要求必须有某些参数,比如,CharFild要求你给出max_length。这些不仅会应用于数据库架构中,也会用于校验,我们不久就会看到。

一个字段也可以有各种各样的可选参数,在本例中,我们会设置vates的默认值为0.

最后,注意已经定义的关系,使用ForeignKey,这会桃酥Django每一个Choice都和某一个Question相关联。Django支持所有普遍的数据库关系模式:多对一、多对多和一对一。

激活models

虽然model的代码量比较少,但是却给了Django大量的信息。有了它,Django就可以:

  • 为polls app创建一个数据库架构(create table )
  • 创建一个通过Question和Choice对象就可以访问数据库的API。

但是首先我们需要去告诉我们的项目polls app已经安装了。
在这里插入图片描述现在Django已经包含了polls app,运行下面的命令:

...\> py manage.py makemigrations polls

就会的到下面的输出:

Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Question
    - Create model Choice

通过运行makemigrations,有告诉了Django你已经对你的models做了改变,并且,你希望将这些改变当做一个migration被存储。

Migration就是Django存储对模型(以及数据库模式)的更改的方式——它们写在硬盘上。你可以读这些migration,就是文件polls/migrations/0001_initial.py。别担心,每当这种文件生成之后,你不需要每次都阅读,但是,它们被设计为可编辑是为了让你可以手工的修改Django改变东西的方式。

这里有一个启动migrations的命令,可以自动的帮你管理数据库结构——这就是migrate,我们一会还会回到这里,但是首先,让我们看一些migration将会运行什么SQL语句。sqlmigrate命令会读取migration的名字,然后返回sql语句。

...\> py manage.py sqlmigrate polls 0001

你会看到类似下面的东西:

...\mysite>py manage.py sqlmigrate polls 0001
--
-- Create model Question
--
CREATE TABLE `polls_question` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `question_text` varchar(200) NOT NULL, `pub_date` datetime(6) NO
T NULL);
--
-- Create model Choice
--
CREATE TABLE `polls_choice` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `choice_text` varchar(200) NOT NULL, `votes` integer NOT NULL, `qu
estion_id` integer 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`);

注意:
1.确切的输出信息取决于你正在使用的什么数据库,上面的例子急于mysql生成的
2.表名是结合app名字自动生成的,由model名字的小写和question和choice组成。(你可以重载这个方法)
3.字段ids是自动添加的。(你可以重载这个方法)
4.按照惯例,Django后面追加‘_id’表示外键关键字段名。(你可以重载这个方法)
5.外键关系是由关键约束明确规定的,不用担心建表之后再执行外键约束,它这是告诉mysql在事务完成之前不要强行外键约束
6.这是对你所使用的数据库定制的,所以具体的数据库字段类型都会自动的帮你处理好。对于引用字段名,例如使用双引号还是单引号也是一样的。
7.sqlmigrate命令不会在你的数据库上自动运行migration,事实上,它打印sql语句到屏幕上,你就可以看到Django认为需要什么SQL语句。这有助于确认Django要做什么,或者数据库管理员需要这些sql语句做一些修改。

如果你有兴趣,你也可以运行 python manage.py check;这会帮你检查你项目中的任何问题,且不会执行migrations,不会影响数据库。

现在,再次运行migrate在数据库中创建这些model表:

...\> py manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Applying polls.0001_initial... OK

migrate命令会接受所有还没有被应用的migrations(Django通过一个在你数据库中叫jdango_migrations的表来追中哪一个migration还没有被应用)并且运行它们,并且和数据库对比,同步化你对models做的改变和数据库结构。

migrations非常强大,能让你随时改变你的models,当你开发你的项目时,不需要删除你的数据库或表在建一个新的。它会专门的更新你正在运行的数据库,且不会丢失数据。我们会在后面的部分更深层次的讲解,但是现在,记住修改model的三步:

  1. 修改你的models(在models.py)
  2. 由于修改,运行python manage.py makemigrations 去创建migrations
  3. 运行python manage.py migrate 去应用这些修改到数据库中

把这些命令分开是因为你需要提交migrations给你的版本控制系统并且应用到你的app中;它们不仅仅是为了让你的开发更容易,在开发中对于其他的开发者也是有用的。

API

现在,让我们跳到与Python交互的的shell命令界面,尝试一些提供给你的Django API。使用下面的命令,调用Python shell:

...\> py manage.py shell

我们正在使用这个替换了简单的输入python,因为manage.py设置了DJANGO_SETTINGS_MODULE 环境变量,它为Django提供了指向mysite/settings.py文件的路径。

如果你在shell中,你可以使用参考文档API

>>> from polls.models import Choice, Question  # Import the model classes we just wrote.

# No questions are in the system yet.
>>> Question.objects.all()
<QuerySet []>

# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

# Save the object into the database. You have to call save() explicitly.
>>> q.save()

# Now it has an ID.
>>> q.id
1

# Access model field values via Python attributes.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# Change values by changing the attributes, then calling save().
>>> q.question_text = "What's up?"
>>> q.save()

# objects.all() displays all the questions in the database.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>

这里使用美国时区输出的,但数据库中以香港时区存储

等等,这个<QuerySet [<Question: Question object (1)>]>根本就没有展示出这个对象,在Question model(polls/models.py)中来修改一下,Question和Choice都添加__str__()方法。
在这里插入图片描述

在models中导入__str__()方法是非常重要的,不仅仅是为了当你在处理即时交互提供自己便利,也是因为对通过Django的自动生成管理有帮助。

再来添加一个自定义方法:

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)

注意导入datetime包和相关工具,如果你对python中的时区处理不太熟悉,你可以参考这里time zone

保存上面的修改,再次运行python manage.py shell,打开一个新的Python shell交互界面:

>>> from polls.models import Choice, Question

# 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()

想了解更多model细节,看访问对象。想看如何使用双下划线头完成字段检索,看字段检索。这里有完整的数据库API,看Datebase API

Django Admin介绍

为你的员工、客户编写一个支持添加,修改和删除页面的admin地址是一件什么枯燥的工作,这并不需要很费脑子。于是,Django完全自动创建了admin的交互界面。

Django被写在一个特别的报社环境中,对于刊物发表人和公共地址有十分明显的界限。地址管理者利用系统图添加新的故事、时间、运动会比分等等,这些内容被展示在公共区域。Django为地址管理员创建了一个统一的地址头编辑内容。

系统不想要参观者使用这个地址,智能地址管理员使用。

创建一个管理员用户

首先我们需要去创建一个可以登录admin地址的用户,运行下面的程序:

...\> py manage.py createsuperuser

输入你想要的用户名,按回车:

Username: admin

输入邮件地址:

Email address: admin@example.com

最后一步就是输入你的密码,你被要求输入密码两次,第二次确认第一次输入的密码:
在这里插入图片描述启动服务器:

...\> py manage.py runserver

现在,打开浏览器,输入网址 http://127.0.0.1:8000/admin/. 你就可以看到admin的登录页面,就可以登录了。
在这里插入图片描述因为系统默认是英文,登录界面是否能翻译成你所使用的语言,这得取决于你的浏览器设置,还有是否Django有你的语言的翻译。

登录后:
在这里插入图片描述这里有些可编辑内容:群组和用户。more detail:Django的认证框架。

安装认证系统

认证自动和Django绑定在一起,发布在module django.contrib.auth.默认情况下,所需要的配置都已经由django-admin startproject命令自动生成保存在settings.py中了。在你的INSTALLED_APPS设置中主要包含两类:

  1. ‘django.contrib.auth’包含了认证框架系统和它的默认models。
  2. ‘django.contrib.contenttypes’是Django内容类型系统,允许和你所创建的models联系。

这里还有一些在MIDDLEWARE设置中:

  1. SessionMiddleware:管理请求中的sessions
  2. AuthenticationMiddleware:联系着使用sessions请求的用户。

有了这些设置,运行命令manage.py migrate为认证相关联的models和已经定义在INSTALLED_APP的app的权限创建必要的数据库表

用法:
Django默认实现
提供默认实现的API参考
自定义用户和认证
Django的密码管理

上一篇:开始Django之旅-part1_构建你的第一个Django app

下一篇:开始Django之旅-part3_Django和view

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值