如何正确的使用和设置Database和Model
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何正确的使用和设置Database和Model相关的知识,希望对你有一定的参考价值。
参考技术A Model是django项目的基础, 如果一开始没有好好设计好, 那么在接下来的开发过程中就会遇到更多的问题. 然而, 大多数的开发人员都容易在缺少思考 的情况下随意的增加或修改model. 这样做的后果就是, 在接下来的开发过程中, 我们不得不做出更多努力来修正这些错误.因此, 在修改model时, 一定尽可能的经过充分的考虑再行动! 以下列出的是我们经常用到的一些工具和技巧:
South, 用于数据迁移, 我们会在每个django项目中都用到. 但到django 1.7时, 将会有django.db.migrations代替.
django-model-utils, 用于处理常见的模式, 例如TimeStampedModel.
django-extensions, 主要用到shell_plus命令, 该命令会在shell中自动载入所有的app的model
1. 基本原则
第一, 将model分布于不同的app中. 如果你的django项目中, 有一个app拥有超过20个model, 那么, 你就应当考虑分拆该app了. 我们推荐每个app拥 有不超过5个model.
第二, 尽量使用ORM. 我们需要的大多数数据库索引都能通过Object-Relational-Model实现, 且ORM带给我们许多快捷方式, 例如生成SQL语句, 读取/更新数据库时的安全验证. 因此, 如果能使用简单的ORM语句完成的, 应当尽量使用ORM. 只有当纯SQL语句极大地简化了ORM语句时, 才使用纯SQL语句. 并且, 在写纯SQL语句是, 应当优先考虑使用raw(), 再是extra().
第三, 必要时添加index. 添加db_index=True到model中非常简单, 但难的是理解何时应该添加. 在建立model时, 我们事先不会添加index, 只有当 以下情况时, 才会考虑添加index:
在所有的数据库查询中使用率在10%-25%时
或当有真实的数据, 或能正确估计出使用index后的效果确实满意时
第四, 注意model的继承. model的继承在django中需要十分小心, django提供了三种继承方式, 1.abstract base class继承(不要和Pyhton标准库的abc模块 搞混), 2.多表(multi-table)继承, 3.proxy model继承. 下表罗列了这三种继承的优劣:
django的创造者和其他许多开发人员都认为, 多表继承的方法不是一个良好的方法. 因此我们强烈建议大家不要使用该方法. 下面列举了一些常见的如何 选择model继承的情形:
如果只有少数model拥有重复的field时, 大可不必使用model继承, 只需要在每个model中添加这些相同的field即可.
如果有足够的model拥有重复的field时, 大多是情况下, 可以使用abstract base class继承, 将相同的field提取到abstract base class 中.
Proxy model继承很少被用到, 和其他两种继承也有着许多不一样之处.
请不要使用多表(multi-table)继承, 因为它既消耗资源又复杂, 如果可以, 尽量使用OneToOneFields和ForeignKeys代替.
django项目中, 创建时间和修改时间这两个field是最用到的, 下面给出一个abstract base class继承的例子:
2. Django Model的设计
如何设计出好的django model可能是最难也是最复杂的一个话题了, 在此, 我们看看一些基本的技巧吧:
a. 规范化
我们首先建议了解数据库规范化(database normalization). 如果你还不清楚这是什么, 那么, 我们强烈建议你先阅读一下相关的书籍, 或搜索"关系 型数据库设计"或"数据库规范化". 在创建django model之前, 应当首先保证设计的数据库是规范化的.
b. cache
正确的使用cache能帮助我们提高数据库的性能. 详细的信息, 我们会在今后的文章中作进一步介绍.
c. 何时使用null和blank
当定义model field时, 我们可以设置null=True和blank=True (默认都是False), 知道何时设置null和blank对于开发人员也是十分重要的, 在下 面的表格中, 我们一一列举了如何使用这两个选项:
d. 什么时候使用BinaryField
在django 1.6中, 新增了BinaryField, 用于储存二进制数据(binary data或 bytes). 对于BinaryField, 我们无法使用ORM的filters, excludes或其他SQL操作. 但在少数情况下, 我们会用到BinaryField, 例如MessagePack格式的内容, 传感器接受的原始数据和压缩数据等. 但需要注意 的是, Binary Data一般都十分庞大, 因此可能会拖慢数据库的速度. 如果发生这一现象, 我们可以将binary data储存在文件中, 然后使用FileField储 存该文件的路径信息.
还有, 不要从BinaryField中直接读取文件并呈献给用户. 因为, 1. 从数据库读写总是比从文件系统读写慢; 2. 数据库备份会变得十分庞大, 花费更多 的时间; 3. 获得文件的过程, 增加了从django到数据库的这一环节.
3. 不要替换默认的Model Manager
从ORM获取model, 实际上是通过django中的Model manager完成的, django为每一个model提供了默认的model manager, 我们不建议将其替换掉, 因为:
当使用model继承时, model会继承 abstract base class model的model manager, 而不会继承非abstract base class的manager.
model的第一个model manager通常作为默认的manager, 当被替换时, 可能会发生不可预测的问题.
4. 数据库事务 (Transaction)
在django 1.6中, ORM默认会autocommit每一个数据库查询, 也就是说, 每次使用m.create()或m.update()时, 在数据库中马上就会做出相应的修 改. 这样做的好处就是简化了初学者对ORM的理解. 但坏处就是, 当一个view中包含两个数据库修改, 可能一个成功, 但另一个失败, 这就可能导致数据库不 完整, 给我们带来很大的危险.
解决这一问题的方法就是使用数据库transaction, 即将一系列数据库操作包含在一个transaction中, 当其中有一个失败时, 其他操作也会自动回退. Django 1.6 为我们带来了一套崭新的既简单又强大的transaction机制, 使我们方便的使用数据库transaction.
a. 将整个http request包裹在transaction中
django给我们提供了一个简单地方法, 将一个http request中的所有数据库操作包裹在transaction中:
只需要在数据库设置中加入'ATOMIC_REQUESTS': True选项, 就能将整个http request包裹在transaction中. 这样做的好处显而易见是是安全, 但 坏处则是性能可能会下降, 因此随着流量的增大, 我们必须采取更针对性的transaction. 其次, 需要注意的是, 回退的只是数据库的状态, 而不包括其他费 数据库项, 例如发送email等. 所以当涉及这些非数据库项时, 我们应当使用transaction.con_atomic_request()修饰(decorate)这些view:
b. 更明确地transaction控制
更明确地transaction控制意味着提高真题web app的性能, 但也意味着更多的开发时间. 大多数网站下, 由于有限的流量, 使用ATOMIC_REQUESTS已 经足够. 在使用手动transaction控制时, 应当注意:
不做数据修改的操作, 应当排除在transaction之外
做数据修改的操作, 则应在transaction内
特殊情况下, 可以违反以上两条
需要注意的是, 当view返回的是django.http.StreamingHttpResponse时, 应当设置ATOMIC_REQUESTS为false, 或使用 transaction.non_atomic_requests将该view修饰. 因为对于view本身, 是可以使用transaction的, 但对于之后生成的response stream触发的额 外SQL查询, 会自动变为django默认的autocommit模式.
转载仅供参考,版权属于原作者。祝你愉快,满意请采纳哦
如何在 my.ini 中将 character_set_database 和 collation_database 设置为 utf8?
【中文标题】如何在 my.ini 中将 character_set_database 和 collation_database 设置为 utf8?【英文标题】:How to set character_set_database and collation_database to utf8 in my.ini? 【发布时间】:2014-04-29 15:14:14 【问题描述】:我已经用谷歌搜索了很多关于这个问题的信息。总结一下,这就是我的my.ini
的样子:
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
[client]
database = abcdef
user = root
password = XXXXXX
default-character-set = utf8
[mysql]
default-character-set=utf8
[mysqld]
character_set_server=utf8
max_connections = 200
init_connect='SET collation_connection = utf8_general_ci'
init_connect='SET NAMES utf8'
当我通过 cmd 进入 mysql 并发出:show variables like "%character%";show variables like "%collation%";
,这就是我得到的:
+--------------------------+---------------------------------+
| Variable_name | Value |
+--------------------------+---------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | D:\env\MySQL5.6\share\charsets\ |
+--------------------------+---------------------------------+
8 rows in set (0.00 sec)
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | utf8_general_ci |
| collation_database | latin1_swedish_ci |
| collation_server | utf8_unicode_ci |
+----------------------+-------------------+
我已经重启了 MySQL 服务,所以谁能告诉我如何将 character_set_database
和 collation_database
更改为 utf8
?非常感谢。
【问题讨论】:
能否请您提及您的 MySQL 版本? 【参考方案1】:这实际上不是my.cnf
(或本例中的my.ini
)中的设置。 mySQL 从数据库自己的排序规则(创建时)获取此设置。为了使这个内联与你想要的 utf8 编码,这样做:
ALTER DATABASE databasename CHARACTER SET utf8 COLLATE utf8_general_ci;
然后在 mysql 上重新启动(不记得是否需要),然后是:
SHOW VARIABLES;
一切都会好起来的, 希望对您有所帮助!
旁注:我认为default-character-set
现在已被弃用(mySQL 5.5+)并且似乎使配置文件变得烦躁。
【讨论】:
我发现SHOW variables WHERE variable_name LIKE '%coll%' OR variable_name LIKE '%char%'
的总结不错
我只有这些数据库:错误(用于 bugzilla)、mysql、information_schema 和 performance_schema。我按照您的建议更改了错误和 mysql 数据库(没有更改 performance_schema 或 information_schema 的权限),但我仍然在 character_set_database 和 character_set_server 中有 utf8mb4。我正在尝试安装 OTRS 帮助台软件,它严格需要 utf8。此外,由于 mysql 的新版本,我无法对 my.cnf 进行建议的更改。你能帮忙吗?
能否避免数据库重启?
在 MySQL 5.7 上不需要重新启动。【参考方案2】:
我做个总结:
确定哪些字符集/排序规则可用
SHOW CHARSET;
SHOW COLLATION;
检查字符集
SHOW VARIABLES LIKE '%character%';
SHOW VARIABLES LIKE '%collation%';
设置字符集(在配置文件 -> my.cnf)
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
检查数据库/表字符集
SHOW CREATE DATABASE databasename;
SHOW CREATE TABLE tablename;
更改数据库/表字符集:
ALTER DATABASE databasename CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE tablename CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
创建数据库/表时设置:
CREATE DATABASE new_db CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;
CREATE TABLE new_table (id INT) CHARSET utf8mb4 COLLATE utf8mb4_general_ci;
注意: 听说Mysql中的utf8不是真正的utf8,utf8mb4才是真正的utf8。 所以,如果你有特殊字符无法保存到 mysql,也许你应该使用 utf8mb4 和 utf8mb4_general_ci
【讨论】:
【参考方案3】:如何配置Character Set
和Collation
。
为每个数据库指定字符设置。例如,应用程序 使用一个数据库的应用程序可能需要对于使用默认 MySQL 字符集存储数据的应用程序 和排序规则(
latin1, latin1_swedish_ci
),无特殊配置 应该是需要的。如果应用程序需要使用 不同的字符集或排序规则,可以配置字符集 信息几种方式:
utf8
,而使用一个数据库的应用程序可能需要utf8
使用其他数据库可能需要 sjis。
在服务器启动时指定字符设置。这会导致服务器
将给定的设置用于所有不做其他应用的应用程序
安排。
如果您构建 MySQL,请在配置时指定字符设置
从源头。这会导致服务器对所有用户使用给定的设置
应用程序,而无需在服务器启动时指定它们。
此处显示的示例为您的问题设置 utf8 字符集,此处还设置排序规则以获得更多帮助(utf8_general_ci
collation`)。
指定每个数据库的字符设置
CREATE DATABASE new_db
DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci;
在服务器启动时指定字符设置
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
在 MySQL 配置时指定字符设置
shell> cmake . -DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci
这可能是一个冗长的答案,但有办法,你可以使用。希望我的回答对你有所帮助。更多信息http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html
【讨论】:
以上是关于如何正确的使用和设置Database和Model的主要内容,如果未能解决你的问题,请参考以下文章
为本地开发设置 django 和 dj-database-url
如何在 my.ini 中将 character_set_database 和 collation_database 设置为 utf8?
如何在 my.ini 中将 character_set_database 和 collation_database 设置为 utf8?
Common Database Security Tasks_5_30
django.core.exceptions.ImproperlyConfigured:constance.backends.database 应用程序未正确安装