• 七、Django的orm之多表操作(一)


    多表操作

    三种关系:一对一,一对多,多对多

    一、数据准备,创建表模型

    1. 配置settings,连接到数据库
      # settings更改配置
      DATABASES = {
      'default': {
      'ENGINE': 'django.db.backends.mysql',
      'NAME': 'orm03',
      'HOST':'127.0.0.1',
      'PORT':3306,
      'USER':'root',
      'PASSWORD':'123'
      }
      }

      # 项目中的init写入:
      import pymysql
      pymysql.install_as_MySQLdb()
      
    2. 在应用中的models.py创建模型
      from django.db import models

      # 比较常用的信息放到这个表里面
      class Author(models.Model): 
          nid = models.AutoField(primary_key=True)
          name=models.CharField( max_length=32)
          age=models.IntegerField()
          authorDetail=models.OneToOneField(
              to="AuthorDetail",
              to_field="nid",
              on_delete=models.CASCADE      # on_delete=models.SET_NULL()设置不级连删除,对方删除后,自己设置为空
          )
          # 与AuthorDetail建立一对一的关系(OneToOneField),一对一的这个关系字段写在两个表的任意一个表里面都可以
          # 就是foreignkey+unique,只不过不需要我们自己来写参数了,并且orm会自动帮你给这个字段名字拼上一个_id,数据库中字段名称为authorDetail_id
      
          
      # 不常用的放到这个表里面
      class AuthorDetail(models.Model):
      
          nid = models.AutoField(primary_key=True)
          birthday=models.DateField()
          # telephone=models.BigIntegerField() 不方便以后查询,需要再转str查,不如直接用str类型
          telephone=models.CharField(max_length=30)
          addr=models.CharField(max_length=64)
      	# 与Author建立一对一的关系(OneToOneField这个关系字段写在两个表的任意一个表里面都可以)
      
          
      class Publish(models.Model):
          nid = models.AutoField(primary_key=True)
          name=models.CharField( max_length=32)
          city=models.CharField( max_length=32)
          email=models.EmailField()  # 相当于CharField,后期可多一层校验规则,判断是否是xx.@...这样的邮箱地址
      
      	# 多对多的表关系,在mysql的时候建立这种关系,需要手动创建一个第三张表,然后写上两个字段,每个字段外键关联到另外两张多对多关系的表;orm的manytomany自动帮我们创建第三张表,两种方式建立关系都可以,以后的学习我们暂时用orm自动创建的第三张表,因为手动创建的第三张表我们进行orm操作的时候,很多关于多对多关系的表之间的orm语句方法无法使用
      #如果你想删除某张表,你只需要将这个表注销掉,然后执行那两个数据库同步指令就可以了,自动就删除了。
      
      
      # 与Publish建立一对多的关系
      # 与Author建立多对多的关系
      class Book(models.Model):
      
          nid = models.AutoField(primary_key=True)
          title = models.CharField( max_length=32)
          publishDate=models.DateField()
          price=models.DecimalField(max_digits=5,decimal_places=2)    
          publish=models.ForeignKey(
              to="Publish",
              to_field="nid",
              on_delete=models.CASCADE
          )
          # 与Publish建立一对多的关系,外键字段建立在多的一方,字段publish如果是外键字段,那么它自动是int类型
          
          #foreignkey里面可以加很多的参数,to指向表,to_field指向你关联的字段,不写这个,默认会自动关联主键字段,on_delete级联删除
          #字段名称不需要写成publish_id,orm在翻译foreignkey的时候会自动给你这个字段拼上一个_id,这个字段名称在数据库里面就自动变成了publish_id
          # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表,并且注意一点,你查看book表的时候,你看不到这个字段,因为这个字段就是创建第三张表的意思,不是创建字段的意思,所以只能说这个book类里面有authors这个字段属性
          authors=models.ManyToManyField(to='Author')
          # 注意不管是一对多还是多对多,写to这个参数的时候,最后后面的值是个字符串,不然你就需要将你要关联的那个表放到这个表的上面
      

      总结:
      创建表:

      一对一:# OneToOneField
      	xx = models.OneToOneField(
              to='表名',
              to_field='字段名',
              on_delete=models.CASCADE
          )
          # to_field可以不写,默认是关联到另一张表的主键
          # on_delete在1.x版本的django中不用写,默认是级联删除的,2.x版本的django要写
          # on_delete=models.SET_NULL()设置不级连删除,对方删除后,自己设置为空
          
      一对多:# ForeignKey
      	xx = models.ForeignKey(
              to='表名',
              to_field='字段名',
              on_delete=models.CASCADE
          )
          
      多对多:# ManyToManyField
      	xx = models.ManyToManyField(to='另外一个表名') #这是自动创建第三表
      	# 还可以手动创建第三张表,(用在还有其他一些自己的字段的时候,暂时忽略)
      	# class BookToAuthor(models.Model):
      	#     book_id = models.ForeignKey(to='Book')
      	#     author_id = models.ForeignKey(to='Author')
      	#     xx = models.CharField(max_length=12)
          
      注意:不管是一对多还是多对多,写to这个参数的时候,最后后面的值是个字符串,不然你就需要将你要关联的那个表放到这个表的上面
      
    3. 执行数据库同步指令:
      python manage.py makemigrations
      python manage.py migrate
      结果如下:

    二、关系表添加记录

    拓展一种添加数据的方式,是django内部提供的一个后台管理系统

    1. 创建一个超级用户:
      python manage.py createsuperuser

      Username (leave blank to use 'administrator'):  yangzm
      Email address:  
      Password:  94211314ming.
      
    2. 访问127.0.0.1:8000/admin/,使用刚注册好的用户名、密码,登录后台管理系统

    3. 在应用app01下的admin.py注册我们要用的表
      from django.contrib import admin
      from app01 import models # 导入models

      # Register your models here.
      
      admin.site.register(models.Author)   # admin.site.register方法注册
      admin.site.register(models.Publish)
      admin.site.register(models.Book)
      admin.site.register(models.AuthorDetail)
      
    4. 重新运行项目,就会发现表已经在后台的管理系统当中了

    5. 点击里面的添加按钮,根据要求,就可以添加数据了

    • 一对一表的增加
      一对一关联的表是:Author表的authorDetail字段关联的 AuthorDetail表的nid字段
      def query(request):

          new_author_detail = models.AuthorDetail.objects.create(
              birthday='1996-02-14',
              telephone='188753698755',
              addr='天界大陆'
          )
          # 方式1:
          models.Author.objects.create(
              name='liangdao',
              age='26',
              authorDetail=new_author_detail # 直接等于对象
          )
          
          new_author_obj = models.AuthorDetail.objects.create(
              birthday='1886-02-14',
              telephone='18615724935',
              addr='幽暗密林'
          )
          # 方式2:(常用)
          models.Author.objects.create(
              name='baobao',
              age='55',
              authorDetail_id=new_author_obj.nid  # 把对象的id属性关联起来
          )
      
    • 一对多的增加
      一对多关联的表是:Book表的publish字段关联的 Publish表的nid字段
      # 方式1:
      models.Book.objects.create(
      title='回村的诱惑',
      publishDate='2018-12-12',
      price=88.88,
      publish=models.Publish.objects.get(nid=1)
      )
      # 方式2:(常用)
      models.Book.objects.create(
      title='回村的诱惑2',
      publishDate='2000-11-11',
      price=45,
      publish_id=models.Publish.objects.get(nid=1).nid
      )

    • 多对多的增加
      多对多关联的表是:Book表的authors字段关联的 Author表的nid字段
      # 方式1:常用
      book_obj = models.Book.objects.get(nid=1)
      book_obj.authors.add([1,2])
      # 方式2:
      author1 = models.Author.objects.get(nid=1)
      author2 = models.Author.objects.get(nid=3)
      book_obj = models.Book.objects.get(nid=2)
      book_obj.authors.add(
      [author1, author2])

    一对一和一对多的删除和单表删除是一样的

    • 一对一的删
      # Author表一对一关联AuthorDetail表
      models.AuthorDetail.objects.get(nid=2).delete()
      # 当AuthorDetail表删除数据时,会影响到Author表,因为级联删除
      models.Author.objects.get(nid=4).delete()
      # 当Author表删除数据时,不会影响到AuthorDetail表
      注意:

      • 表一关联表二,做了级联,表二删除,表一跟着删除
      • 表一关联表二,没做级联,表二删除,表一报错
      • 表一关联表二,无论做没做级联,表一删除数据,都不会影响到表二
    • 一对多的删
      # Book表一对多关联Publish表
      models.Publish.objects.get(nid=2).delete()
      # Publish表删除数据,影响到Book表
      models.Book.objects.get(nid=7).delete()
      # Book表删除数据,不会影响到Publish表

    • 多对多关系的删除
      实际上就是去删除多对多自动生成的表中的关系的记录
      # Book表多对多的关联Author表
      book_obj = models.Book.objects.get(nid=3)
      book_obj.authors.remove(3)
      # 先找到book里id是3的书,然后通过authors属性删除作者id是3的数据

          book_obj = models.Book.objects.get(nid=3)
          book_obj.authors.remove(*[2,3])
          # 先找到book里id是3的书,然后通过authors属性删除作者id是2和3的数据
          
          book_obj = models.Book.objects.get(nid=3)
          book_obj.authors.clear()
          # 先找到book里id是3的书,然后通过authors属性找到关系表,删除所有id是3的书数据
          
          book_obj = models.Book.objects.get(nid=3)
          book_obj.authors.clear()
          book_obj.authors.add(*[1,])
          # 先删除所有id是3的书数据,然后给id是3的书加入一个id是1的作者
          
          book_obj = models.Book.objects.get(nid=3)
          book_obj.authors.set('1')
          # 同样完成上述需求,先清空再添加(set必须给个参数,否则报错)
          
          book_obj = models.Book.objects.get(nid=3)
          book_obj.authors.set(['5','6']) 
          # 删除然后更新,添加多个
      

      注意:

      • Book表删除数据,会影响到关系表的数据
      • Author表删除数据,也同样会影响到关系表的数据
    1. 更新
    • 一对一
      models.Author.objects.filter(nid=6).update(
      name='baoge',
      age='16',
      authorDetail=models.AuthorDetail.objects.get(nid=5)
      # authorDetail_id = 4 两种方式
      )

    • 一对多
      models.Book.objects.filter(pk=6).update(
      title='回娘家的诱惑',
      price=188,
      publish=models.Publish.objects.get(pk=2)

      	models.Publish.objects.filter(pk=2).update(
      		id=4, # 没有级联更新,报错!!
          )
              
      # 注:默认级联删除,级联更新没有默认
      
    • 多对多
      # 就是set

          book_obj = models.Book.objects.get(nid=3)
          book_obj.authors.set('1')
          # 同样完成上述需求,先清空再添加(set必须给个参数,否则报错)
          
          book_obj = models.Book.objects.get(nid=3)
          book_obj.authors.set(['5','6']) 
          # 删除然后更新,添加多个
  • 相关阅读:
    SQL server 和Oracle 序列
    AD 域服务简介(一)- 基于 LDAP 的 AD 域服务器搭建及其使用(转)
    Windows Server 2008 R2 搭建DNS服务器(转)
    windows7下搭建HTTP服务器
    解决vcenter 6.0 vcsa安装插件时报错的问题
    Windows server 2008R2系统登录密码破解
    vmware Horizon 7 与远程桌面(mstsc)兼容性问题解决办法
    VCSA服务重启命令
    如何哄女朋友开心(转)
    快速搭建一个本地的FTP服务器 win10及win7
  • 原文地址:https://www.cnblogs.com/yangzm/p/11234608.html
Copyright © 2020-2023  润新知