ORM简介
对象关系映射(Object Relational
Mapping),它的实质就是将关系数据(库)中的业务数据用对象的形式表示出来,并通过面向对象(Object-Oriented)的方式将这些对象组织起来,实现系统业务逻辑的过程。
在ORM过程中最重要的概念是映射(Mapping),通过这种映射可以使业务对象与数据库分离。从面向对象来说,数据库不应该和业务逻辑绑定到一起,ORM则起到这样的分离作用,使数据库层透明,开发人员真正的面向对象。
两个关键词 “映射” 和 “对象”
- 映射(Mapping) —— 把表结构映射成类
- 对象 —— 像操作类对象一样,操作数据库里的数据
映射
就是把表转换为对象的形式
sql语句到对象
从图中可以看出通过映射,是的ORM大大提高了开发效率,但是要知道有利既有弊:
ORM优点:
- 实现了代码与数据操作的解耦合
- 不需自己写原生sql, 提高开发效率
- 防止SQL注入, 通过对象操作的方式,默认就是防止sql注入的。
缺点:
- 牺牲性能, 对象到原生SQL势必会有转换消耗,对性能有一定的影响
- 复杂语句力不从心, 一些复杂的sql语句,用orm对象操作的方式很难实现,就还得用原生sql
Models模型
Django 的models把数据库表结构映射成了一个个的类, 表里的每个字段就是类的属性。数据库有很多字段类型,int,float,char等, Django的models类针对不同的字段也设置了不同的类属性。
AutoField #An IntegerField that automatically increments according to available IDs
BigAutoField #A 64-bit integer, guaranteed to fit numbers from 1 to 9223372036854775807.
BigIntegerField #-9223372036854775808 to 9223372036854775807
BinaryField #A field to store raw binary data. It only supports bytes assignment
BooleanField
CharField
DateField #e.g 2019-04-27
DateTimeField #e.g 2019-04-27 17:53:21
DecimalField
DurationField #storing periods of time ,e.g [DD] [HH:[MM:]]ss[.uuuuuu]"
EmailField
FileField #存储文件
FloatField
ImageField #Inherits all attributes and methods from FileField, but also validates that the uploaded object is a valid image.
IntegerField
GenericIPAddressField #IP地址,支持ipv4
NullBooleanField #Like a BooleanField, but allows NULL as one of the options
PositiveIntegerField #Like an IntegerField, but must be either positive or zero (0). Values from 0 to 2147483647
PositiveSmallIntegerField #only allows positive values from 0 to 32767
SlugField # A slug is a short label for something, containing only letters, numbers, underscores or hyphens.
SmallIntegerField
TextField #A large text field.
TimeField #A time, represented in Python by a datetime.time instance.
URLField
UUIDField #A field for storing universally unique identifiers. Uses Python’s UUID class.
除了普通的表字段,针对外键也有映射
ForeignKey # 外键关联
ManyToManyField #多对多
OneToOneField # 1对1
下面用orm设计一个博客表
首先是需求:
- 每个用户有自己的账户信息
- 用户可以发文章
- 文章可以打多个标签
根据需求我们需要设计三张表,分别是Account、Article、Tag
其中Article和Tag表是多对多的关系,多对多的意思就是一篇文章可以对应有多个标签,而一个标签也可以对应多篇文章
那么多对多的关系在表中是如何储存的呢?
可以用在两表之间再建一个表作为桥梁
在 django中, 有个专门的字段,叫ManyToManyField, 就是用来实现多对多关联的,它会自动生成一个如上图一样的第3张表来存储多对多关系。
models.py
from django.db import models
# Create your models here.
class Account(models.Model):
"""账户表"""
username = models.CharField(max_length=64, unique=True)
email = models.EmailField(unique=True)
password = models.CharField(max_length=125)
register_data = models.DateTimeField(auto_now_add=True)
signature = models.CharField("签名",max_length=255, null=True)
class Article(models.Model):
"""文章表"""
title = models.CharField(max_length=255, unique=True)
content = models.TextField()
account = models.ForeignKey("Account", on_delete=models.CASCADE)
tags = models.ManyToManyField("Tag")
pub_data = models.DateField()
class Tag(models.Model):
"""标签表"""
name = models.CharField(max_length=64, unique=True)
data = models.DateTimeField(auto_now_add=True)
每个字段其实都是一个独立的对象,一张表其实是很多类的组合。
上面好多字段里还跟了些参数,下面是一些常用的参数:
null #If True, Django will store empty values as NULL in the database. Default is False.
blank #If True, the field is allowed to be blank. Default is False.
db_column #The name of the database column to use for this field. If this isn’t given, Django will use the field’s name.
db_index #If True, a database index will be created for this field.
default #The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.
editable # django admin中用,后面讲
help_text # django admin中用,后面讲
primary_key # If True, this field is the primary key for the model.
unique #If True, this field must be unique throughout the table
unique_for_date #Set this to the name of a DateField or DateTimeField to require that this field be unique for the value of the date field. For example, if you have a field title that has unique_for_date="pub_date", then Django wouldn’t allow the entry of two records with the same title and pub_date.
unique_for_month #Like unique_for_date, but requires the field to be unique with respect to the month.
unique_for_year
verbose_name #A human-readable name for the field. If the verbose name isn’t given, Django will automatically create it using the field’s attribute name
配置数据库
表建完之后,接下来要连接数据库
首先配置数据库信息
Django支持多种数据库,Sqlite、Mysql、Oracle、PostgreSQL,默认的是小型文件数据库Sqlite
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
但我们使用的数据库是mysql,即改为如下配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'USER': 'root,
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
不过注意,python3
连接mysql的得使用pymysql,MysqlDB模块300年没更新了,但django默认调用的还是MySQLdb, so pymysql有个功能可以让django以为是用了MySQLdb. 即在项目目录下的__init__.py中加上句代码就好
import pymysql
pymysql.install_as_MySQLdb()
不加的话,连接数据库时会报错
同步数据库
首先需要在cmd中创建数据库
先登入mysql
然后通过指令创建数据库
create database test charset utf8;
然后就可以同步了
1. 生成同步文件,
django自带一个专门的工具叫migrations, 负责把你的orm表转成实际的表结构,它不旦可以帮自动创建表,对表结构的修改,比如增删改字段、改字段属性等也都能自动同步。只需通过下面神奇的命令。
python manage.py makemigrations
然后就可以看到以下类似的信息
$ python manage.py makemigrations
Migrations for 'app01':
app01/migrations/0001_initial.py
- Create model Account
- Create model Article
- Create model Tag
- Add field tags to article
这时app下的migrations目录里多了一个0001_initial.py的文件 ,这个文件就是因为这条命令而创建的,migrations工具就会根据这个文件来创建数据库里的表。
2.同步数据
输入指令 python manage.py migrate
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, app01, auth, contenttypes, sessions
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 app01.0001_initial... 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 sessions.0001_initial... OK
(venv_django2) Alexs-MacBook-Pro:mysite alex$
此时登录mysql,然后show tables; 会发现创建了很多表
mysql> show tables;
+----------------------------+
| Tables_in_luffy_dev2 |
+----------------------------+
| app01_account | #对应Account表
| app01_article | #对应Article表
| app01_article_tags | #自动创建的Article to Tag的多对多关联表
| app01_tag | #对应Tag表
| auth_group | #下面这些,都是django 自带的表,这个是自动用户系统的组
| auth_group_permissions | #自带的组与权限的多对多关联表
| auth_permission | #自带权限表
| auth_user | #用户表
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log | #现在你的无法理解
| django_content_type | #现在你的无法理解
| django_migrations | #纪录migartions工具同步纪录的表
| django_session | #现在你的无法理解
+----------------------------+
14 rows in set (0.00 sec)
现在表建好了,就可以输入数据了
在pycharm自带的terminal中输入指令
python manage.py shell 进入连接好数据库的django python环境
(venv) C:\Users\76390\PycharmProjects\my_site>python manage.py shell
Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:43:08) [MSC v.1926 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from app01 import models
创建
。。。
待更