Djnago(五)--数据库模型Models

数据库设置

简介

  • mysite/settings.py是Django模块的一些设置。包括APP,TIME_ZONE……

  • 默认情况下,数据库使用SQLite。如果你对数据库操作不熟悉,或者只是对Django感兴趣,可以选择SQLite数据库,操作简单。原因: SQLite,是一款轻型的数据库,并且包含在Python中。当使用时不需要安装软件。

  • 但是,当我们开始编写真正的项目时,希望使用一个相对稳定的的数据库。(比如PostgreSQL,Mysql,Orcale等,避免在开发过程中更改数据库。)

  • 如果想要修改默认数据库引擎,必须安装对应的数据库(eg:Mysql,Oracle等),并在polls/setting.py中更改数据库默认值:

数据库引擎设置内容
sqlitedjango.db.backends.sqlite3
postgresqldjango.db.backends.postgresq
mysqldjango.db.backends.mysql
oracledjango.db.backends.oracle

Mysql范例

mysql软件设置

# 安装mysql,rhel6版本直接安装mysql-server,rhel7及以上安装mariadb-server,也是mysql的一个分支;
[root@foundation0 ~]# yum install mariadb-server -y

# 启动mysql服务
[root@foundation0 ~]# systemctl  start mariadb

# 设置mysql服务开机自启动
[root@foundation0 ~]# systemctl enable mariadb

# 数据库初始化设置,给一个密码;
[root@foundation0 ~]# mysql_secure_installation ^C

# 通过root的密码登陆,创建一数据库DjangoTest;
# 拓展: 如果想要更加安全,可以创建一个数据库用户,授权只能对DjangoTest操作,这个是数据库的部分,这里不赘述;
[root@foundation0 ~]# mysql -uroot -pwestos
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 27
Server version: 5.5.52-MariaDB MariaDB Server

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

# 创建数据库DjangoTest;
MariaDB [(none)]> create database DjangoTest;
Query OK, 1 row affected (0.00 sec)

Django的设置

# 编辑文件mysite/setting.py文件,对整个项目的数据库和时区等进行设置;
# 将原先的默认数据库sqlite修改如下:

DATABASES = {
    'default': {
        # 指定数据库引擎;
        'ENGINE': 'django.db.backends.mysql',
        # 指定要操作的数据库名称;
        'NAME':'django',
        # 指定登陆数据库的用户名,用户必须对数据库有操作权限;
        'USER':'root',
        # 指定登陆数据的密码;
        'PASSWORD':'westos',
        # 指定数据库所在主机,127.0.0.1是回环地址IP,代表本机;
        # 当然实际应用时,数据库与其他主机是分离的,直接写安装了数据库的那台主机IP即可;
        'HOST':'127.0.0.1',
        # 指定数据库的端口,默认为3306,如果有修改,则写修改后的端口;
        'PORT':'3306',
        # 有关数据库的其他设置;
        'OPTIONS':{
            # 设置Mysql数据库工作模式为严格模式,否则运行时会产生警告,后面启动时再做详细解释;
            'init_command':'SET sql_mode="STRICT_TRANS_TABLES"',
            # 设置数据库的默认编码格式为utf-8(可变长编码格式);
            'charset':'utf8',
        }
    }
}



# 时区设置
TIME_ZONE = 'Asia/Shanghai'

根据设置创建默认的数据库表

不过,这些App至少使用了一个数据库表,因此在使用它们之前,我们需要在数据库中创建表。为此,运行以下命令:

$ python manage.py  migrate


# 执行结果如下:
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, 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 polls.0001_initial... OK
  Applying sessions.0001_initial... OK

# 创建默认数据库表完成后,可以直接去数据库里面查看信息;

创建数据库模型

简单的polls 应用程序中,我们将创建两个模型:
- 问题: 包含一个问题和出版日期;
- 选择:包含选择的文本和投票计数。每个都与一个问题相关联。

下面的代码通过创建python的类,自动生成对应的数据库表,编辑文件polls/models.py文件如下:

# 编辑文件polls/models.py

from django.db import models

# 创建表Question,字段有question_text(问题内容)和pub_date(问题发布时间);
#       question_text的数据类型为字符串类型,最大长度为200;
#       pub_date的数据类型为时间类型;

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')




# 创建数据库表为Choice,字段由question(一个外键,与Question表的内容关联),choice_text(选择的文本)和votes(投票数,默认设置为0);

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的子类。django.models.Model模型包含多个类变量,每个类变量代表模型中的一个数据库字段。每个字段都由一个字段类的实例来表示。(eg:, CharField for character fields and DateTimeField for datetimes.)

  • 每一个字段实例(e.g. question_text or pub_date)是这个字段的名称,以机器的格式。我们可以在Python代码中使用,它也是数据库的列名。

  • 一些字段实例需要参数。例如,CharField要求设置max_length。我们将投票的默认值设置为0。

  • 在Choice中创建了一个外键,与Question关联起来。代表Django每个Choice都与一个Qusetion相关。Django中支持所有常见的数据库关系:多对多、多对多和一对一。

使用(激活)数据库模型

这一小部分的模型代码为Django提供了很多信息。有了它,Django可以:

  • 为这个polls应用程序创建一个数据库模式(创建表语句
  • 创建一个用于访问问题和选择对象的Python数据库访问API。

但首先,我们需要告诉我们的项目,投票应用程序已经安装好了。

要在我们的项目中包含应用程序,我们需要在INSTALLED_APPS设置中添加一个对这个应用配置的引用。PollsConfig类在polls/apps.py文件,因此编辑文件mysite/setting.py文件如下:


INSTALLED_APPS = [
    # 只需要添加polls应用程序的设置;其他的本身存在;
    'polls.apps.PollsConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

现在将polls应用程序添加到项目中,想要生效,执行shell命令如下:

$ python manage.py makemigrations polls


# 执行结果如下:
Migrations for 'polls':
  polls/migrations/0001_initial.py:
    - Create model Choice
    - Create model Question
    - Add field question to choice

By running makemigrations, you’re telling Django that you’ve made some changes to your models (in this case, you’ve made new ones) and that you’d like the changes to be stored as a migration.

通过运行makmigrations,告诉Django对模型做了一些更改,并且希望将这些更改存储起来。

有一个命令可以为您运行迁移,并自动管理数据库模式——这称为迁移,我们稍后将讨论它——但是首先,让我们看看迁移将运行的SQL是什么。sqlmigration命令接受迁移名称并返回其SQL:

$ python manage.py sqlmigrate polls 0001

# 返回结果如下,是一串SQL语句:
BEGIN;
--
-- 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);
--
-- Create model Question
--
CREATE TABLE `polls_question` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `question_text` varchar(200) NOT NULL, `pub_date` datetime NOT NULL);
--
-- Add field question to choice
--
ALTER TABLE `polls_choice` ADD COLUMN `question_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`);
COMMIT;
  • 检测是否有语法错误
$ python manage.py  check
  • 生成对应的数据库表
$ python manage.py  migrate
  • 总结:当应用程序的model.py做了修改,需要做的操作如下:
# to create migrations for those changes,shell命令执行;
$ python manage.py makemigrations 

#  to apply those changes to the database,shell命令执行;
Run python manage.py migrate

通过django API管理数据库

进入交互式Python shell中,使用Django提供的API。要调用Python shell,请使用以下命令:

$ python manage.py shell

我们使用这个方法,而不是简单地输入“python”,因为 manage.py 设置环境变量DJANGO_SETTINGS_MODULE,该变量为Django提供了Python导入模块路径到您的mysite/settings.py 文件。

# 通过该shell命令进入django的API使用环境;
$ python manage.py shell

基本的API使用

当已经在shell中时,就可以使用django的API如下所示:

# 导入我们编写的模块类;
>>> from polls.models import Question, Choice  

# 显示为空,目前系统中没有写入任何问题,数据为空;
>>> Question.objects.all()
<QuerySet []>



# 插入数据,即创建一个新的问题;
# 在默认的设置文件中,设置time zones是开启的; 
# 所以在django中记录问题发布时间选择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,这个id可能是1也可能是1L,这取决于你使用的数据库,eg:(下面操作的mysql数据库显示为1L)
>>> q.id
1L
# 访问你数据库模型中的内容;
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)


# 修改数据库的内容,修改结束后记得保存
>>> q.question_text = "What's up?"
>>> q.save()
# 通过objects.all()方法显示数据库中的所有问题,但此时返回的是一个对象,后面会进行优化;
>>> Question.objects.all()
<QuerySet [<Question: Question object>]>

对类进行优化,使用API

是一个不太有用的对象表示。解决方法: 编辑polls/models.py文件,Question and Choice类中添加特殊方法str,编辑内容如下:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models


class Question(models.Model):
    ......
    # 当用户直接打印类时,返回的不是对象本身,而是对象的__str__返回的内容;
    def __str__(self):
        return self.question_text
    # 下面让我们添加一个自定义方法,仅用于演示:
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)


class Choice(models.Model):
    ......
    def __str__(self):
        return self.choice_text

当已经在shell中时,就可以使用django的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?>]>

# 获取该问题发布的年份;导入了django自带的timezone模块;
>>> 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提供了一个快速通过主键查看信息的方式,如下:
# 下面的操作与 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_set.all()
<QuerySet []>

# 创建三个新的选择;
>>> 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对象访问与之关联的Question对象内容;
>>> c.question
<Question: What's up?>

# 显示所有的选择,并根据choice_set.count方法计算用户提交的选择;
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3

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

拓展文档: Django通过API对数据的操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值