Django框架(六):Django模型系统 ① 模型基础

1.Django 的 ORM 介绍

ORM:对象关系映射 (英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping)),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 。从效果上说,它其实是创建了一个可在编程语言里使用的--“虚拟对象数据库”。
作用:在实际开发中不方便直接对数据库进行sql语句操作,所以我们将sql数据库中的表,直接映射成python中的对象,对对象进行增删改查的操作。

2.数据库配置

  • 安装pymysql
pip install pymysql -i https://pypi.douban.com/simple
  • 修改项目目录下的__init__.py文件
import pymysql
pymysql.install_as_MySQLdb()
  • 手动创建一个当前项目的空的数据库,准备一个有创建数据库权限的用户
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mydb               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.29 sec)

mysql> create database crm charset=utf8;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| crm                |
| mydb               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
6 rows in set (0.00 sec)
  • 配置settings.py文件
DATABASES = {
    'default': {
        ##定义引擎 'ENGINE': 'django.db.backends.sqlite3', ## python默认的小型文件数据库
        ##定义文件 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        'ENGINE': 'django.db.backends.mysql', ## 定义mysql引擎
        'NAME': 'crm', ## 数据库名
        'USER': 'admin',
        'PASSWORD': 'Root110qwe',
        'HOST':'127.0.0.1',
        'PORT':'3306',
    }
}

3.模型的创建与映射

模型:什么是模型,模型就是django.db.models.Model的一个子类

模型类对应数据库中的数据表,类属性对应的表字段名

a.创建模型
  • 模型定义在app文件夹下的models.py文件中
from django.db import models

# Create your models here.

class Students (models.Model): # 一个类代表一个数据表
    id = models.AutoField(primary_key=True) ##创建一个可以自动生成的主键,这条也可以不写,Django中会自动生成主键
    name = models.CharField(verbose_name='姓名',
                            max_length=20)   ##创建字符类型字段,最大长度为20,设置提示信息'姓名'
                                            ### max_length为CharField的必须参数
    age = models.SmallIntegerField(verbose_name='年龄',null=True) ##创建值可以为null的小整型字段,
    sex = models.SmallIntegerField(default=1)   ##创建缺省值为1的小整型字段
    qq = models.CharField(max_length=20,null=True)
    phone = models.CharField(max_length=20,null=True)
   c_time = models.DateTimeField(verbose_name='创建时间',auto_now_add=True)  ##创建日期时间类型字段,自动创建当前时间
b.激活模型
  • 注册应用
  • 创建迁移
    什么叫迁移:"在django中对数据库中的结构有任何改变都叫做迁移"
  1. 这条命令会在app目录的migrations目录下创建一个迁移文件
(crm) pyvip@VIP:~/projects/crm$ python manage.py makemigrations teacher
Migrations for 'teacher':
  teacher/migrations/0001_initial.py
    - Create model Students
  1. 如果要看这个迁移文件会产生什么样的SQL语句,可以执行下面这条命令
(crm) pyvip@VIP:~/projects/crm$ python manage.py sqlmigrate teacher 0001
BEGIN;
--
-- Create model Students
--
CREATE TABLE `teacher_students` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(20) NOT NULL, `age` smallint NULL, `sex` smallint NOT NULL, `qq` varchar(20) NULL, `phone` varchar(20) NULL, `c_time` datetime(6) NOT NULL);
COMMIT;
  1. 执行迁移文件操作数据库,将对模型的改动应用到数据库(底层就是执行了SQL语句)
(crm) pyvip@VIP:~/projects/crm$ python manage.py migrate teacher
Operations to perform:
  Apply all migrations: teacher
Running migrations:
  Applying teacher.0001_initial... OK

查看所创建的表

mysql> show tables;
+-------------------+
| Tables_in_crm     |
+-------------------+
| django_migrations |
| teacher_students  |
+-------------------+
2 rows in set (0.00 sec)

teacher_students就是刚才创建的数据表,表名 = appname_模型类
django_migrations是所有的迁移记录数据表,里面记录了所有的迁移记录

python manage.py migrate appname 这条命令执行的操作:

  • 在app中查找迁移文件,并且去django_migrations表中查找,如果有没有执行的迁移文件就去执行
  • 执行迁移生成的SQL语句
  • 如果成功,会在django_migrations表中增加一条记录

4.简单的数据的增删改查

在Django模型中,一个类代表一张数据表,一个类的实例代表一条数据

  • Django调试环境
(crm) pyvip@VIP:~/projects/crm$ python manage.py shell
Python 3.6.6 (default, Sep 12 2018, 18:26:19) 
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 

增加有几种方法
a. 第一种方式

In [1]: from teacher.models import Students            #导入这个类                            

In [2]: Students.objects.all()        #查询这个数据表的所有数据                                             
Out[2]: <QuerySet []>      #当前数据为空

In [3]: s = Students()           #创建这个类的实例,即一条数据                                                  

In [4]: s                                                             
Out[4]: <Students: Students object (None)>    # 这条数据为空             

In [5]: s.name = '小米'                 #为这条数据的一个字段赋值                                           

In [6]: s.age = 18                                                                 

In [7]: s.save()                          #每次赋值之后必须要保存,否则数据不会上传到数据库中                                         

In [8]: Students.objects.all()                                                     
Out[8]: <QuerySet [<Students: Students object (1)>]>        #查询到一条数据

然后在数据库中就能查询到这条数据

mysql> select * from teacher_students;
+----+--------+------+-----+------+-------+----------------------------+
| id | name   | age  | sex | qq   | phone | c_time                     |
+----+--------+------+-----+------+-------+----------------------------+
|  1 | 小米   |   18 |   1 | NULL | NULL  | 2019-03-27 18:17:46.167806 |
+----+--------+------+-----+------+-------+----------------------------+
1 row in set (0.00 sec)

b. 第二种方式

In [10]: stu = Students.objects.create(name='小李',age=22)        #直接用create方法直接创建         

In [11]: stu.name                                                                  
Out[11]: '小李'

In [12]: stu.id                                                                    
Out[12]: 3

  • 删除
In [13]: stu.delete()                                                              
Out[13]: (1, {'teacher.Students': 1})

改一条数据

In [14]: stu.age = 33                                                              

In [15]: stu.save()          

改所有的数据

In [27]: Students.objects.all().update(age=15)                                     
Out[27]: 3
  • 查询
    查一条数据和所有的数据
In [16]: Students.objects.all()                 #查所有的数据                                   
Out[16]: <QuerySet [<Students: Students object (1)>, <Students: Students object (2)>, <Students: Students object (4)>]>

In [17]: res = Students.objects.all()                                              

In [18]: print(res.query)                                                          
SELECT `teacher_students`.`id`, `teacher_students`.`name`, `teacher_students`.`age`, `teacher_students`.`sex`, `teacher_students`.`qq`, `teacher_students`.`phone`, `teacher_students`.`c_time` FROM `teacher_students`

In [19]: Students.objects.get(pk=1)          #查询主键为1的一条数据,如果查询到多条数据就报错,主键默认参数为`pk`                                      
Out[19]: <Students: Students object (1)>

首先我们看一下这几条语句,什么是objects,什么是QuerySet,什么是all()方法

  • objects是一个Manager类型的对象,定义在from django.db import models中,是默认生成的,也就是objects = Modes.Manage(),他提供一个数据库和模型对象交互的接口(api)。Students.objects.all()翻译过来就是Students类通过Manager管理器,用all接口返回一个QuerySet对象

在res = Students.objects.get()或者res = Students.objects.all()中

  • Students是类名,就是你在model中创建的类
  • objects是django默认的管理器对象,帮你完成各种操作。
  • get()或者all()是API,一种内置函数,不同的操作调用不同的API就可以了。
  • res通过all()得到的就是queryset()对象,也就是查询对象的集合。

QuerySet是惰性的,只有调用的时候才会执行

带条件查询
In [25]: res = Students.objects.filter(name='小米',age=18)                         

In [26]: res                                                                       
Out[26]: <QuerySet [<Students: Students object (1)>]>

补充:模型元数据

我们要定义模型的一些属性,比如排序选项(attr:~Options.ordering),数据库表名(db_table),或是人可读的单复数名(verbose_name和verbose_name_plural)时,必须要用到元数据,内部使用Meta类来给模型赋予元型态数据

实例:

from django.db import models

class Ox(models.Model):
    horn_length = models.IntegerField()

    class Meta:
        ordering = ["horn_length"]    #默认按horn_length字段的升序排序
        verbose_name_plural = "oxen"    #设置模型对象的复数名称
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容