七、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']) 
        # 删除然后更新,添加多个

猜你喜欢

转载自www.cnblogs.com/yangzm/p/11234608.html