文章目录
第5章 深入Django模型层之使用篇
5-2 数据库迁移
数据备份
(venv) D:\Python_projects\backend-3-9>python manage.py dumpdata --exclude=contenttypes --exclude=auth.Permission > mysite_alldata.json
表结构同步
Django默认可使用多个数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'slave': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'vx_backend',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': '3306'
}
}
- 同步数据库表结构
python manage.py migrate --run-syncdb --database slave
(venv) D:\Python_projects\backend-3-9>python manage.py migrate --run-syncdb --database slave
Operations to perform:
Synchronize unmigrated apps: messages, staticfiles
Apply all migrations: admin, auth, authorization, contenttypes, sessions
Synchronizing apps without migrations:
Creating tables...
Running deferred SQL...
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 auth.0009_alter_user_last_name_max_length... OK
Applying authorization.0001_initial... OK
Applying sessions.0001_initial... OK
(venv) D:\Python_projects\backend-3-9>
与sqllite数据库表结构都一样
在同步表结构后,DATABASE部分可以注释了
数据迁移
数据迁移
(venv) D:\Python_projects\backend-3-9>python manage.py loaddata mysite_alldata.json
Installed 81 object(s) from 1 fixture(s)
(venv) D:\Python_projects\backend-3-9>
5-3 数据库索引
索引概述
应该被索引的字段
更改model属性都需要
(venv) D:\Python_projects\backend-3-9>python manage.py makemigrations
Migrations for 'authorization':
authorization\migrations\0002_auto_20200531_1818.py
- Alter field nickname on user
(venv) D:\Python_projects\backend-3-9>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, authorization, contenttypes, sessions
Running migrations:
Applying authorization.0002_auto_20200531_1818... OK
Diango添加索引两种方法
# Create your models here.
class User(models.Model):
# open_id
open_id = models.CharField(max_length=64, unique=True)
# 昵称
nickname = models.CharField(max_length=256) # index = True
# 关注的城市
focus_cities = models.TextField(default='[]')
# 关注的星座
focus_constellations = models.TextField(default='[]')
# 关注的股票
focus_stocks = models.TextField(default='[]')
class Meta:
indexes = [
models.Index(fields=["open_id", "nickname"]),
models.Index(fields=["nickname"])
]
5-4 关系映射
三种关系映射
Django表达三种映射
关系映射实战
根据 不同用户可以选择添加不同app应用,关系为多对多
app model
from django.db import models
# Create your models here.
# 入口功能清单描述
class App(models.Model):
appid = models.CharField(primary_key=True, max_length=32) # 唯一ID
category = models.CharField(max_length=128) # 分类
application = models.CharField(max_length=128) # 功能名字
name = models.CharField(max_length=128) # 中文名字
publish_date = models.DateField() # 发布时间
url = models.CharField(max_length=128) # 请求链接
desc = models.TextField() # 描述
def to_dict(self):
return {
'appid': self.appid,
'category': self.category,
'application': self.application,
'name': self.name,
'publish_date': self.publish_date,
'url': self.url,
'desc': self.desc
}
def __str__(self):
return str(self.to_dict())
def __repr__(self):
return str(self.to_dict())
用户model
# -*- encoding=utf8 -*-
from django.db import models
from apis.models import App
# Create your models here.
class User(models.Model):
# open_id
open_id = models.CharField(max_length=64, unique=True)
# 昵称
nickname = models.CharField(max_length=256, db_index=True)
# 关注的城市
focus_cities = models.TextField(default='[]')
# 关注的星座
focus_constellations = models.TextField(default='[]')
# 关注的股票
focus_stocks = models.TextField(default='[]')
# 菜单app
menu = models.ManyToManyField(App)
class Meta:
indexes = [
# models.Index(fields=['nickname'])
models.Index(fields=['open_id', 'nickname'])
(venv) D:\Python_projects\backend-3-9>python init.py
init.py:28: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.
apps = yaml.load(f)
not exist, appid: f18ba49825b634f44e8cdfb694ecaa13
not exist, appid: 549eaaf72cb23716e2b1313acfaed23c
not exist, appid: 7b27422f98f13eb2610f1996ec757be7
not exist, appid: a381d410bea99d3618cc6cd431c32b0f
not exist, appid: 833cfd91bc1ac638ecd3764715b443ef
5-5 数据库操作
django使用原生SQL的方法
使用extra:
models.Book.objects.filter(publisher__name=‘传说中的申小五’).extra(where=[‘price>50’])
models.Book.objects.filter(publisher__name=‘传说中的申小五’, price__gt=50)
models.Book.objects.extra(select={‘count’: ‘select count(*) from hello_Book’})
使用raw:
Book.objects.raw(‘select * from hello_Book’) # 返回模型实例
执行自定义SQL语言:
from django.db import connection
cursor=connection.cursor()
cursor.execute("insert into hello_author(name) values('传说中的申小五')")
cursor.execute("update hello_author set name='abc' where name='bcd'")
cursor.execute("delete from hello_author where name='abc'")
cursor.execute("select * from hello_author")
raw=cursor.fetchone() # 返回结果行游标直读向前,读取一条
cursor.fetchall() # 读取所有
数据库函数
第6章 深入Django模型层之优化篇
6-1 章节导学
6-2 理解模型变更与迁移
数据变更的sql语句显示
(venv) D:\Python_projects\backend-3-9>python manage.py sqlmigrate authorization 0004
BEGIN;
--
-- Remove index authorizati_nicknam_b76290_idx from user
--
DROP INDEX `authorizati_nicknam_b76290_idx` ON `authorization_user`;
--
-- Add field menu to user
--
CREATE TABLE `authorization_user_menu` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `user_id` integer NOT NULL, `app_id` varchar(32) NOT NULL);
--
-- Alter field nickname on user
--
CREATE INDEX `authorization_user_nickname_248a4fcf` ON `authorization_user` (`nickname`);
ALTER TABLE `authorization_user_menu` ADD CONSTRAINT `authorization_user_m_user_id_b7aaa9f0_fk_authoriza` FOREIGN KEY (`user_id`) REFERENCES `authorization_user` (`id`);
ALTER TABLE `authorization_user_menu` ADD CONSTRAINT `authorization_user_menu_app_id_13ca5893_fk_apis_app_appid` FOREIGN KEY (`app_id`) REFERENCES `apis_app` (`appid`);
ALTER TABLE `authorization_user_menu` ADD CONSTRAINT authorization_user_menu_user_id_app_id_4d3d9382_uniq UNIQUE (`user_id`, `app_id`);
COMMIT;
历史迁移记录
(venv) D:\Python_projects\backend-3-9>python manage.py showmigrations authorization
authorization
[X] 0001_initial
[X] 0002_auto_20200531_1818
[X] 0003_auto_20200531_1823
[ ] 0004_auto_20200531_1912
(venv) D:\Python_projects\backend-3-9>
如果没有 X, 在说明没有执行 migrate到db
迁移文件详解
6-3 懒加载与预加载
使用python manage.py shell ,导入mode的类属性,使用query可以显示查询的sql语句。
预加载的两种方法
再用query属性看一下SQL语句,select_related()使用JOIN获取了模型的数据。这样就预先加载了外键关联的对象,再次调用关联对象时就不会访问数据库了。
6-4 数据库长连接
-
尽少的链接次数,集中查询
因为创建和关闭链接的时间和单词查询的时间类似,一开一关大大浪费性能
-
避免负优化:
使用CONN_MAX_AGE配置限制DB连接寿命
CONN_MAX_AGE默认值是0
每个DB连接的寿命保持到该次请求结束
不建议开发模式下使用CONN_MAX_AGE
6-5 数据库操作规范
-
判断是否应该建索引的条件
1、较频繁的作为查询条件的字段应该创建索引
2、唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件
3、增、删、改操作较多的数据库字段不适合建索引