Django 之 Models(Models 模型 & 数据表关系)

举报
ruochen 发表于 2021/03/27 23:09:52 2021/03/27
【摘要】 Models 模型ORMdjango连接数据库models类的使用定义和数据库表映射的类字段常用参数数据库的迁移数据相关操作查看数据库中的数据查找数据添加数据常见查找方法 数据库表关系1:1 OneToOneaddquerychange 1:N OneToManyaddquery N:N ManyToManyaddquery ...

[欢迎阅读本专栏其他文章]
Django 之路由篇
Django 之视图篇
Django 之模板篇

Models 模型

ORM


  • ObjectRelationMap: 把面向对象思想转换成关系数据库思想,操作上把类等价于表格
  • 类对应表格
  • 类中的属性对应表中的字段
  • 在应用中的models.py 文件中定义class
  • 所有需要使用ORM的class都必须是 models.Model 的子类
  • class 中的所有属性对应表格中的字段
  • 字段的类型都必须使用 modles.xxx 不能使用python中的类型
  • 在django中,Models 负责跟数据库交互

django连接数据库

  • 自带默认数据库Sqlite3
    • 关系型数据库
    • 轻量级
  • 建议开发用splite3,部署用mysql之类数据库
    • 切换数据库在settings中进行设置

        # django 连接 mysql
        DATABASES = [ 'default' = { 'ENGINE': 'django.db.backends.mysql', 'NAME': '数据库名', 'PASSWORD': '数据库密码', 'HOST': '127.0.0.1', 'PORT': '3306', }
        ]
      
            
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
    • 需要在项目文件下的__init__文件中导入pymysql包

      # 在主项目的__init__文件中
      
      import pymysql pymysql.install_as_MySQLdb()
      
            
           
      • 1
      • 2
      • 3
      • 4

models类的使用

定义和数据库表映射的类


  • 在应用中的models.py 文件中定义class
  • 所有使用ORM 的class都必须是models.Models 的子类
  • class中的所有属性对应表格中的字段
  • 字段的类型都需使用 models.xxx 不能使用python 中的类型

字段常用参数


  • max_length: 规定数值的最大长度
  • blank: 是否允许字段为空,默认不允许
  • null: 在DB中控制是否保存为null,默认为False
  • default: 默认值
  • unique: 唯一
  • verbose_name: 假名

数据库的迁移


  1. 在命令行中,生成数据迁移的语句(生成sql语句)

     python3 manage.py makemigrations
    
        
       
    • 1
  2. 在命令行中,输入数据库迁移的指令

     python3 manage.py migrate # 如果迁移过程中出现没有变化或者报错,可以尝试强制迁移 # 强制迁移命令
     python3 manage.py makemigrations 应用名
     python3 manage.py migrate 应用名
    
        
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  3. 对于默认数据库,为了避免出现混乱,如果数据库中没有数据,每次迁移前可以把系统自带的sqlite3数据库删除

数据相关操作

查看数据库中的数据

1. 启动命令行: python3 manage.py shell
ps: 注意点: 对orm的操作分为静态函数和非静态函数两种,静态是指在内存中只有一份内容存在,调用的时候使用 类名. 的方式,如果修改了那么所有使用的人都会受影响
2. 在命令行中导入对应的映射类 from 应用.models import 类名
3. 使用 objects 属性操作数据库,objects 是模型中实际和数据库进行交互的 Manager 类的实例化对象
4. 查询命令 - 类名.objects.all() 查询数据表中的所有内容,返回的结果是一个 QuerySet 类型,实际上是类列表中装这个一个一个数据对象 - 类名.objects.filter(条件)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

查找数据

# from 应用名.models import 类名
from myapp.models import Student

# 查询Student表中的所有数据,得到的是一个QuerySet类型
Student.objects.all()

# 如果要取出所有QuerySet类型中的所有数据对象,需要遍历取出所有的对象,再用对象.属性来查看值
s = Student.object.all()
for each in s:
	print(each.name , each.age , each.address , each.phone)

# 如果要进行过滤筛选,使用filter()方法
Student.objects.filter(age=18)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

添加数据

对象 = 类()   # 使用类实例化对象
对象.属性 = 值  # 给对应的对象的属性赋值
对象.save()  # 必须要执行保存操作,否则数据没有进入数据库


# python3 manage.py shell 命令行中添加数据

# from 应用名.models import 类名

from myapp.models import Student

# 实例化对象
s = Student()

# 给对象的属性赋值
s.name = 'ruochen'
s.address = 'xxx'
s.phone = '18888888888'
s.age = 18

# 保存数据
s.save()

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

常见查找方法

  1. 通用查找格式: 属性名 _ _ (用下面的内容) =值
    • gt : 大于
    • gte : 大于等于
    • lt : 小于
    • lte : 小于等于
    • range: 范围
    • year : 年份
    • isnull : 是否为空
  2. 查找等于指定值的格式: 属性名 = 值
  3. 模糊查找: 属性名 _ _ (使用下面的内容) = 值
    • exact : 精确等于
    • iexact: 不区分大小写
    • contains: 包含
    • startwith: 以…开头
    • endwith: 以…结尾
# 查找年龄大于18的老师
ta = Teacher.objects.filter(age__gt=18)

# 小于20
ta = Teacher.objects.filter(age__lt=20)

# 查找course中包含a字母的老师
ta = Teacher.objects.filter(course__contains="a")

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

数据库表关系

  • 多表连查:利用多个表联合查找莫一项信息或多项信息
  • models.py
from django.db import models

# Create your models here.

class School(models.Model): school_id = models.IntegerField() school_name = models.CharField(max_length=20) # teacher_set # my_manager = models.OneToOneField("Manager") def __str__(self): return self.school_name

class Manager(models.Model): manager_id = models.IntegerField() manager_name = models.CharField(max_length=20) # 建立一对一关系 my_school = models.OneToOneField(School) def __str__(self): return self.manager_name

class Teacher(models.Model): teacher_name = models.CharField(max_length=20) my_school = models.ForeignKey("School")

class Student(models.Model): student_name = models.CharField(max_length=20) teachers = models.ManyToManyField("Teacher")

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

1:1 OneToOne

  • 建立关系:在模型任意一边即可,使用OneToOneField

add

  • 添加没有关系的一边,直接实例化保存就可以

      s = School()
      s.school_id = 2
      s.school_name = "sssss"
      s.save() 
    
        
       
    • 1
    • 2
    • 3
    • 4
  • 添加有关系的一边,使用create方法

      # 方法一
      m = Manager()
      m.manager_id = 10
      m.manager_name = "ruochen"
      m.my_school = s
      m.save() # 方法二
      m = Manager.objects.create(manager_id=20, manager_name="ruo", my_school=ss[0])
    
        
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

query

  • 由子表查母表: 由子表的属性直接提取信息

       Manager.objects.get(manager_name="ruochen").my_school.school_name
    
        
       
    • 1
  • 由母表标查子表:使用双下划线

     In [43]: s = School.objects.get(manager__manager_name="ruochen")
     In [44]: s
     Out[44]: <School: sssss>
    
        
       
    • 1
    • 2
    • 3

change

  • 单个修改使用save

      In [47]: s.school_name = "111"
      In [48]: s.save()
    
        
       
    • 1
    • 2
  • 批量修改使用update

    In [53]: ss = School.objects.all()
    In [54]: type(ss)
    Out[54]: django.db.models.query.QuerySet
    In [55]: ss.update(school_name="666")
    Out[55]: 2
    In [57]: ss
    Out[57]: [<School: 666>, <School: 666>
    
        
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 无论对子表还是母表的修改

  • delete: 直接使用delete

1:N OneToMany

  • 一个表格的一个数据项/对象等,可以有很多个另一个表格的数据项
  • 比如:一个学校可以有很多老师,但一个老师只能在一个学校上班
  • 使用上
    • 使用ForeignKey
    • 在多的那一边,比如上边的例子就是在Teacher的表格里进行定义

add

  • 跟一对一方法类似,通过create和new来添加

  • create:把属性都填满,然后不需要手动保存

  • new: 可以属性或者参数为空,必须用save保存

      # 方法一
      In [3]: t1 = Teacher()
      In [4]: t1.teacher_name = "若尘"
      In [5]: t1.my_school = ss[0]
      In [6]: t1.save()
      In [7]: ts = Teacher.objects.all()
      In [8]: ts
      Out[8]: [<Teacher: Teacher object>]
      In [9]: ts[0].teacher_name
      Out[9]: '若尘' # 方法二
      In [21]: t2 = Teacher.objects.create(teacher_name="ruochen2", my_school=ss[0])
      In [22]: ts = Teacher.objects.all()
      In [23]: ts
      Out[23]: [<Teacher: Teacher object>, <Teacher: Teacher object>]
      In [24]: ts[1].teacher_name
      Out[24]: 'ruochen2'
    
        
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

query

  • 以学校和老师的列子为准

  • 如果知道老师, 查学校,则通过增加的关系属性,直接使用

  • 例如,查询t1老师是哪个学校的

      In [30]: t1.my_school
      Out[30]: <School: 666>
    
        
       
    • 1
    • 2
  • 反查

    • 查询学校所有的老师,则系统自动在学校模型下添加属性

        In [34]: s1.teacher_set.all()
        Out[34]: [<Teacher: Teacher object>, <Teacher: Teacher object>] In [36]: s1.teacher_set.all().filter(teacher_name="若尘")
        Out[36]: [<Teacher: Teacher object>]
      
            
           
      • 1
      • 2
      • 3
      • 4
      • 5

N:N ManyToMany

  • 表示任意一个表的数据可以拥有对方表格多项数据,反之亦然
  • 比如典型例子就是老师和学生的关系
  • 使用上,在任意一方,使用ManyToMany定义,只需要定义一边

add

  • 添加老师,则在student.teachers.add()

      In [2]: stus = Student.objects.all()
      In [3]: stus
      Out[3]: []
      In [4]: s1 = Student()
      In [5]: s1.student_name = "ruochen"
      In [6]:
      In [6]: t1 = Teacher.objects.all()
      In [7]: t1
      Out[7]: [<Teacher: Teacher object>, <Teacher: Teacher object>]
      In [9]: t1.teacher_name
      Out[9]: '若尘'
      In [12]: s1.save()
      In [17]: s1.teachers.add(t1)
      In [18]: s1.teachers.all()
      Out[18]: [<Teacher: Teacher object>]
      In [19]: s1.save()
      In [24]: s1.teachers.all()[0].teacher_name
      Out[24]: '若尘'
    
        
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

query

  • 跟一对多类似,使用_set查询

      In [25]: t1.student_set.all()
      Out[25]: [<Student: Student object>]
    
        
       
    • 1
    • 2

文章来源: ruochen.blog.csdn.net,作者:若尘,版权归原作者所有,如需转载,请联系作者。

原文链接:ruochen.blog.csdn.net/article/details/107139975

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。