Mac系统下Django学习实践(三)--搭建简单数据库
在 Django 里写一个数据库驱动的 Web 应用的第一步是数据库结构设计。所以今天我们将搭建一个简单的数据库,创建第一个模型。
数据库配置
我们今天作为初学者,使用Django自带的数据库SQLite,无需安装其他任何东西,但是如果需要用其他的数据库,需要额外的安装和配置,比较繁琐不在今天的讨论范围,有兴趣的可以参考官方文档。
- 在sign/sign/settings.py中配置一下中国的时区,这将会在之后用到系统时间记录时准确定为中国时间。
TIME_ZONE = 'Asia/Shanghai'
- 用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
输出:
这就是上面提到的迁移,在acsign/migrations/0001_initial.py 里可以阅读刚刚的模型迁移数据。
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
显示:
至此,模型更改后的数据库同步更改成功。
试用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>]>