Mac系统下Django学习实践(三)--搭建简单数据库

在 Django 里写一个数据库驱动的 Web 应用的第一步是数据库结构设计。所以今天我们将搭建一个简单的数据库,创建第一个模型。

数据库配置
我们今天作为初学者,使用Django自带的数据库SQLite,无需安装其他任何东西,但是如果需要用其他的数据库,需要额外的安装和配置,比较繁琐不在今天的讨论范围,有兴趣的可以参考官方文档

  1. 在sign/sign/settings.py中配置一下中国的时区,这将会在之后用到系统时间记录时准确定为中国时间。
TIME_ZONE = 'Asia/Shanghai'
  1. migrate
    $ python manage.py migrate根据settings.py中的配置为INSTALLED_APPS 中默认启动的app创建需要的数据表。
INSTALLED_APPS = [
    'django.contrib.admin',				//管理员站点
    'django.contrib.auth',				//认证授权系统
    'django.contrib.contenttypes',	//内容类型框架
    'django.contrib.sessions',			//会话框架
    'django.contrib.messages',		//消息框架
    'django.contrib.staticfiles',		//静态文件管理框架
]

注释:如果是INSTALLED_APPS发生改变,则先通过运行 makemigrations 命令,Django 检测模型文件的修改并且把修改的部分储存为一次迁移,后面创建我们自己的数据表时会用到。

搭建模型
Django 遵循 DRY准则 --我们只需要定义数据模型,它便会自动可以为我们做很多数据库的事情。
首先我们为一个最简单的活动签到系统设计两个数据模型–活动创建模型和签到模型,在sign/acsign/models.py中编辑如下:

import datetime
from django.db import models
from django.utils import timezone

# Create your models here.

//活动创建模型
class Activity(models.Model):
    activity_theme = models.CharField(max_length=200)
    activity_creator = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    
    def __str__(self):
        return self.activity_theme
    def was_published_recently(self):
        return self.pub_date >= timezone.now()
    datetime.timedelta(days=1)

//签到模型
class Sign(models.Model):
    activity = models.ForeignKey(Activity, on_delete=models.CASCADE)
    sign_name = models.CharField(max_length=200)
    sign_date = models.DateTimeField('date sign')
    
    def __str__(self):
        return self.sign_name

字符字段被表示为 CharField ,日期时间字段被表示为 DateTimeField ,这将告诉 Django 每个字段要处理的数据类型。def定义的这些str、was_published_recently函数我们暂且先不管。

**模型
上面提到说我们只需要把创建好的模型信息给Django,它便能自动为我们做很多事情,这部分中可以看到Django可以:

  • 为acsign这个应用创建数据库(SQL语句)。

1,首先我们在sign/sign/settings.py中的INSTALLED_APPS把acsign包含进来,因为 AcsignConfig 类写在文件 acsign/apps.py 中,所以它的点式路径是 ‘acsign.apps.AcsignConfig’

INSTALLED_APPS = [
    'acsign.apps.AcsignConfig',
    ……
]

2,接着在控制台运行

python manage.py makemigrations acsign

输出:
Mac系统下Django学习实践(三)--搭建简单数据库
这就是上面提到的迁移,在acsign/migrations/0001_initial.py 里可以阅读刚刚的模型迁移数据。
Mac系统下Django学习实践(三)--搭建简单数据库
3,还可以通过在控制台执行

python manage.py sqlmigrate acsign 0001

把上面的信息转换为可以阅读的SQL语句如下:

BEGIN;
--
-- Create model Activity
--
CREATE TABLE "acsign_activity" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "activity_theme" varchar(200) NOT NULL, "activity_creator" varchar(200) NOT NULL, 
"pub_date" datetime NOT NULL);
--
-- Create model Sign
--
CREATE TABLE "acsign_sign" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
"sign_name" varchar(200) NOT NULL, 
"sign_date" datetime NOT NULL,
 "activity_id" integer NOT NULL REFERENCES "acsign_activity" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "acsign_sign_activity_id_9b108f13" ON "acsign_sign" ("activity_id");
COMMIT;

4,现在,再次运行 migrate 命令,在数据库里创建新定义的模型的数据表:

python manage.py migrate

显示:
Mac系统下Django学习实践(三)--搭建简单数据库
至此,模型更改后的数据库同步更改成功。

试用database API
上面提到说我们只需要把创建好的模型信息给Django,它便能自动为我们做很多事情,这部分中可以看到Django可以:

  • 创建可以与 Activity 和 Sign 对象进行交互的 Python 数据库 API。

1,通过控制台的

python manage.py shell

命令进入python,这样比起直接进入python,这样会根据manage.py 中设置的 DJANGO_SETTINGS_MODULE 环境变量,让 Django 根据 sign/settings.py 文件来设置 Python 包的导入路径。
2,进入python命令行后便可以试用database API来试用添加、查询、修改等操作表中的数据啦:


In [1]: from acsign.models import Activity, Sign                                

In [2]: Activity.objects.all()                                                  
Out[2]: <QuerySet [<Activity: class activity>]>

In [3]: q = Activity.objects.get(pk=1) 
   ...: q.was_published_recently()                                              
Out[3]: False

In [4]: q.id                                                                    
Out[4]: 1

In [5]: q.activity_creator                                                      
Out[5]: ''

In [6]: q.activity_creator = "Iris"                                             

In [7]: q                                                                       
Out[7]: <Activity: class activity>

In [8]: q.sign_set.all()                                                       
Out[8]: <QuerySet []>

In [9]: from django.utils import timezone                                      

In [10]: q.sign_set.create(sign_name='hebe', sign_date=timezone.now()) 
    ...: q.was_published_recently()                                             
Out[10]: False

In [11]: q.sign_set.create(sign_name='nana', sign_date=timezone.now())          
Out[11]: <Sign: nana>

In [12]: a = q.sign_set.create(sign_name='lily', sign_date=timezone.now())      

In [13]: a.activity                                                             
Out[13]: <Activity: class activity>

In [14]: a.id                                                                   
Out[14]: 3

In [15]: q.sign_set.all()                                                       
Out[15]: <QuerySet [<Sign: hebe>, <Sign: nana>, <Sign: lily>]>

In [16]: current_year = timezone.now().year                                     

In [17]: Sign.objects.filter(activity__pub_date__year=current_year)             
Out[17]: <QuerySet [<Sign: hebe>, <Sign: nana>, <Sign: lily>]>