《Tango With Django2》Chapter5笔记 -- Model & DB

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来includeregister 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. 再次运行填充脚本,将可靠的测试数据插入到新数据库中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值