Django用对象关系映射器(Object Relational Mapper, ORM)¹来访问存储在数据库中的数据
本质上,存储在数据库表中的数据是通过Django模型封装的。模型是描述数据库表数据的Python对象。Django提供了一些方法,让你可以通过相应的Python模型对象来操作数据,而不是直接通过SQL操作数据库。您向ORM发出的任何命令都会自动转换为相应的SQL语句。
【本章学习内容】了解Django及其ORM的数据管理基础知识(即数据库操作)
1. 回忆Rango App的需求
(1) Rango本质上是一个网页目录——包含到其他外部网站链接的网站
(2) 有几个不同的网页category,每个类别没有、有一个或多个链接(多对一关系)
(3) 1个category – 1个name,多个visits,多个likes
(4) 1个page属于一个特定的category;1个page – 1个title,1个URL,多个View
2. 告诉Django 项目的DB
使用default DB,即setting.py中的DATABASE变量(如下):
⚠️不要用 git push DB
(将db.sqlite3 添加到 .gitignore文件中就不会git push;或者*.pyc)
3. 创建Models
Models存储在在Workspace/tango_with_django_project/rango/models.py中
分别为category和page创建Model,基类均从django.db.models.Model中继承
from django.db import models
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
# unique=True ⇒ 字段名设置为唯一,意味着可以使用该字段作为主键
def __str__(self):
return self.name
# 如果没有实现__str__(),它将显示为<Category: Category object>
# __str__()就是Python中的toString()
class Page(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
# CASCADE指令Django在类别被删除时删除与该类别相关的页面
title = models.CharField(max_length=128)
url = models.URLField()
views = models.IntegerField(default=0)
def __str__(self):
return self.title
Django内置字段类型
CharField: 存储字符类型;max_length - 指定最大字符长度
URLField: 存储URL类型;max_length - 指定最大字符长度
IntegerField: 存储int类型
DateField: 存储Python datetime.date对象
每个字段如果设置unique=True,即字段名设置为唯一,意味着每个类别名称必须是唯一的,意味着可以使用该字段作为主键
每个字段可指定附加属性,如默认值(default='value'
)、为空(NULL =True
)或不为空(NULL =False
)
Django模型之间关系的字段
ForeignKey:一对多
OneToOneField:一对一
ManyToManyField:多对多
4. 创建和迁移DB
(1) 初始化DB
要创建数据库和所有相关的表 => 打开终端/命令提示符,并导航到项目的根目录(其中存储了manage.py模块)运行下面的命令:
$ python manage.py migrate
输入如下:
(2) 创建一个superuser来管理DB,执行如下命令:
$ python manage.py createsuperuser
并输入username,email address,password
[删除superuser]
在终端输入:
$ python manage.py shell
#接着输入
>>> from django.contrib.auth.models import User
>>> User.objects.get(username='yfan',is_superuser=True).delete()
# ‘yfa’替换成自己的用户名
>>> exit()
(3 )创建&更新Models/Tables
当你改变应用的Models时,你需要通过manage.py中的makemigrations命令来注册这些改变,运行如下命令:
python manage.py makemigrations rango
运行结果如下图(在这个命令完成后,检查rango/migrations目录,查看已经创建了一个Python脚本名为0001_initial.py,其中包含为该特定迁移创建数据库模式所需的所有必要细节):
如果您想检查Django ORM为给定的迁移向数据库引擎发出的底层SQL,您可以发出以下命令(rango是你的应用程序的名称,而0001是你想要查看的SQL代码的迁移):
$ python manage.py sqlmigrate rango 0001
(4)为应用程序创建迁移之后,需要将它们提交到数据库。再次发出migrate命令:
$ python manage.py migrate
运行结果如下图(这个输出确认数据库中已经创建了数据库表):
5. Django Models & Shell
可以直接从Django shell中与Django Model交互——这是一个非常有用的调试工具
(1) 要访问shell,我们需要从Django项目的根目录中再次调用manage.py
执行如下命令( 这将启动一个Python解释器实例,并为你加载项目的设置):
$ python manage.py shell
在终端中输入下面的代码与Model进行交互:
# 从Rango应用程序导入Category模型
>>> from rango.models import Category
# 显示当前所有类别
>>> print(Category.objects.all())
# 因为没有定义任何类别,所以我们得到一个空的QuerySet对象
<QuerySet []>
# 创建一个新的category对象,并将其保存到数据库中
>>> c = Category(name='Test')
>>> c.save()
# Now list all the category objects stored once more.
>>> print(Category.objects.all())
# You'll now see a 'Test' category.
<QuerySet [<Category: Test>]
# Quit the Django shell.
>>> quit()
6. 配置Admin接口
[将设置两个Model管理界面]
(1) 运行下面命令,访问http://127.0.0.1:8000/admin/,用之前设置的superuser登陆
$ python manage.py runserver
缺少了为Rango定义的Category和Page Models => 需让Django知道我们想要包含它们
(2) 打开rango/admin.py文件。用admin.site.register()
方法注册要包含的个类:
from django.contrib import admin
from rango.models import Category, Page
admin.site.register(Category)
admin.site.register(Page)
重新runserver,会看到有Category&Page两个Model,点击Category可以看到Test Category:
将Test Category删除
管理界面中Categorys的拼写错误可以用verbose_name_plural
修改:
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
class Meta:
verbose_name_plural = 'Categories'
def __str__(self):
return self.name
7.创建填充脚本
利用填充脚本往DB中添加数据
(1) 在Workspace/tango_with_django_project/目录中创建一个名为populate_rango.py的新文件
(2) populate_rango.py内容:
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tango_with_django_project.settings')
import django
django.setup()
from rango.models import Category, Page
# Populate()对已创建的类别保持tab。
# 例如,对一个新类别的引用被存储在本地变量c中。
# 这是因为Page需要Category reference。在populate()中调用add_cat()和add_page()之后,该函数将循环遍历全新的Category和相关的Page对象,并在终端上显示它们的名称。
def populate():
# 首先,我们将创建包含要添加到每个类别中的页面的词典列表。
# 然后,我们将为我们的类别创建一个字典的字典。
# 这可能看起来有点混乱,但它允许我们遍历每个数据结构,并将数据添加到我们的模型中
python_pages = [
{'title': 'Official Python Tutorial', 'url':'http://docs.python.org/3/tutorial/'},
{'title':'How to Think like a Computer Scientist', 'url':'http://www.greenteapress.com/thinkpython/'},
{'title':'Learn Python in 10 Minutes', 'url':'http://www.korokithakis.net/tutorials/python/'}
]
django_pages = [
{'title':'Official Django Tutorial', 'url':'https://docs.djangoproject.com/en/2.1/intro/tutorial01/'},
{'title':'Django Rocks', 'url':'http://www.djangorocks.com/'},
{'title':'How to Tango with Django', 'url':'http://www.tangowithdjango.com/'}
]
other_pages = [
{'title':'Bottle', 'url':'http://bottlepy.org/docs/dev/'},
{'title':'Flask', 'url':'http://flask.pocoo.org'}
]
cats = {'Python': {'pages': python_pages},
'Django': {'pages': django_pages},
'Other Frameworks': {'pages': other_pages} }
# 如果你想添加更多的类别或页面,将它们添加到上面的字典中
# 下面的代码遍历cats字典,然后添加每个类别,然后添加该类别的所有相关页面。
for cat, cat_data in cats.items():
c = add_cat(cat)
for p in cat_data['pages']:
add_page(c, p['title'], p['url'])
# Print out the categories we have added.
for c in Category.objects.all():
for p in Page.objects.filter(category=c):
print(f'- {c}: {p}')
# 创建新的page
def add_page(cat, title, url, views=0):
p = Page.objects.get_or_create(category=cat, title=title)[0]
p.url=url
p.views=views
p.save()
return p
# 创建新的category
def add_cat(name):
c = Category.objects.get_or_create(name=name)[0]
c.save()
return c
# 从这里开始执行
# __name__ == '__main__' 允许Python模块充当可重用模块或独立的Python脚本
# 因此,if中的代码将只在模块作为一个独立的Python脚本运行时执行。导入模块不会运行这段代码;不过可以完全访问任何类或函数
if __name__ == '__main__':
print('Starting Rango population script...')
populate()
get_or_create()
方法:在填充脚本中创建模型实例。如果该实例不存在在DB中,则创建;如果存在,则返回对特定Model的实例的引用
get_or_create()
方法返回一个(object, created)
元组。object
是对Model实例的引用;created
是一为boolean值,如果必须创建Model实例,则返回True。
get_or_create()[0] :只返回object reference
(3) 运行下面代码来运行填充脚本,会得到下列输出:
$ python populate_rango.py
(4)重新启动server,检查是否有数据填充
7. Setup Model总结
(1) 配置DB => 告诉Django将要使用的DB即在settings.py中配置DATABASES;也可以在app的admin.py模块中注册任何模型,然后让它们可以通过基于web的管理界面访问
(2) 添加Model
a. 在App的models.py文件中创建你的新Model
b. 如果管理界面可以访问新Model,更新admin.py来include
并register
Model
c. 迁移
$ python manage.py makemigrations <app_name>
d. 运行下列代码来更新数据库中的改变
$ python manage.py migrate
e. 为的新Model创建/编辑填充脚本
(3) 刷新DB需要的操作:
a. 如果DB正在运行,停止Django server
b. 对于SQLite数据库,删除数据库 => 在你的Django项目目录下的sqlite3文件
c. 如果改变了APP的Model,你需要运行下面的代码(<app_name>替换为Django应用的名字(即rango)):
$ python manage.py makemigrations <app_name>
如果您的模型没有更改,跳过此步骤。
d. 运行下面命令创建一个新的DB文件(如果您正在运行SQLite),并将数据库表迁移到数据库中
$ python manage.py migrate
e. 使用下面命令创建一个新的管理员帐户
$ python manage.py createsuperuser
f. 再次运行填充脚本,将可靠的测试数据插入到新数据库中