Django之ORM多表操作之增删改

一.创建表

作者表:
class Author(models.Model): 
    nid = models.AutoField(primary_key=True)
    name=models.CharField( max_length=32)
    age=models.IntegerField()
    # 与AuthorDetail建立一对一的关系,一对一的这个关系字段写在两个表的任意一个表里面都可以
    authorDetail=models.OneToOneField(to="AuthorDetail",to_field="nid",on_delete=models.CASCADE)
    # orm会自动帮你给这个字段名字拼上一个_id,数据库中字段名称为authorDetail_id
	参数解释:
	    # 注意:
        # 1.x版本默认是级联的可以不加on_delete=models.CASCADE   但是2.x版本一定要加
        # models.SET_NULL:不做级联 如果关联的表AuthorDetail将数据删除了 那么Author将为null
        # 如果关联的表中有定义id字段可以使用to_field="id字段名" 如果关联的表中没有定义id字段 mysql默认会加上id这个字段 这里的to_field就不用定义,to指向表,to_field指向你关联的字段
        # 一对一的关系用OneToOneField来建立,这个关系字段写在两个表的任意一个表里面都可以

#作者信息表
class AuthorDetail(models.Model):
    nid = models.AutoField(primary_key=True)
    birthday=models.DateField()
    telephone=models.CharField()
    addr=models.CharField( max_length=64)
    
#出版社
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 但是使用EmailField方便后续校验是不是Email格式


#书籍表
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建立一对多的关系,外键字段建立在多的一方,字段publish如果是外键字段,那么它自动是int类型
    publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE)
    #foreignkey里面可以加很多的参数,都是需要咱们学习的,慢慢来,to指向表,to_field指向你关联的字段,
    # 不写这个,默认会自动关联主键字段,on_delete级联删除字段名称不需要写成publish_id,orm在翻译foreignkey的时候会自动给你这个字段拼上一个_id,这个字段名称在数据库里面就自动变成了publish_id
    # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,
    # 自动创建第三张表,并且注意一点,你查看book表的时候,你看不到这个字段,
    # 因为这个字段就是创建第三张表的意思,不是创建字段的意思,
    # 所以只能说这个book类里面有authors这个字段属性
    authors=models.ManyToManyField(to='Author') #注意不管是一对多还是多对多,写to这个参数的时候,最后后面的值是个字符串,不然你就需要将你要关联的那个表放到这个表的上面


上述表关系:
	# 作者表和作者详细信息表是一对一的关系
	# 作者表和书籍表是多对多的关系
	# 出版社和书籍表是一对多的关系   但是实际业务中不一定是
	# 在orm中可以通过属性来创建第三张表 authors=models.ManyToManyField(to='Author',)
	# 一对一:models.OneToOneField(to="AuthorDetail",to_field='id',on_delete=models.CASCADE)
	# 一对多:models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE)
	# 多对多:models.ManyToManyField(to='Author',) 自动创建第三张表

这里django中是使用ManyToManyField来创建第三张表,如果我们单独创建的话需要这样:

这张表就是作者和书籍的多对多的关系  这种方式没法使用orm提供多对多表中的一些操作方法,所以不建议使用
我们直接使用authors=models.ManyToManyField(to='Author',)就会形成第三张表,将来我们直接使用authors来操作第三张表
class BookToAuthor(models.Model):
    book_id = models.ForeignKey(to='Book')
    author_id = models.ForeignKey(to='Author')

创建出来的第三张表:
在这里插入图片描述
表关系梳理流程:
在这里插入图片描述

二.使用admin给关系表添加记录

admin后台创建数据:
之前我们学单表的时候是直接写代码添加或者在Python console里面也可以添加,现在我们学习在admin后台给表添加数据

from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),  #访问这个地址就可以到我们的admin后台
]  

在这里插入图片描述
这里需要用户名密码,我们要先创建(命令):createsuperuser
在这里插入图片描述要想在我们admin后台操作这些表,需要在我们APP应用下admin.py文件下注册表信息:

from django.contrib import admin
from app02 import models

# Register your models here.
admin.site.register(models.Book)
admin.site.register(models.Author)
admin.site.register(models.AuthorDetail)
admin.site.register(models.Publish)
注意:注册完需要重启一下我们的项目

在这里插入图片描述

三.orm语句增删改查

orm语句添加数据:

**1.1一对一增加:**

    new_author_detail = models.AuthorDetail.objects.create(
        birthday='2012-12-15',
        telephone='138316464',
        addr='黑龙江哈尔滨'
    )

    方式一:
    models.Author.objects.create(
        name='麻子',
        age=25,
        authorDetail=new_author_detail  #直接写model对象
    )

    方式二:
    obj= models.AuthorDetail.objects.filter(addr='山西临汾').first()
    models.Author.objects.create(
        name='麻子',
        age=25,
        authorDetail_id=obj.nid,
    )

**1.2一对多增加:**

    方式一:
    models.Book.objects.create(
        title='张三的床头故事',
        publishDate='2019-07-22',
        price=23,
        publishs=models.Publish.objects.get(nid=4)
    )

    方式二:
    obj = models.Publish.objects.get(nid=3)
    models.Book.objects.create(
        title='张三的床头故事2',
        publishDate='2019-07-23',
        price=15,
        publishs_id=obj.nid   常用
    )


**1.3多对多增加:**
方式一:
book_obj = models.Book.objects.get(nid=1)
book_obj.authors.add(*[1,2])  #常用

方式二:
author1 = models.Author.objects.get(nid=2)
author2 = models.Author.objects.get(nid=3)
book_obj = models.Book.objects.get(nid=5)
book_obj.authors.add(*[author1, author2])

orm语句删除数据:

# 一对一和一对多的和单表删除是一样的
models.AuthorDetail.objects.get(nid=1).delete()  #级联删除
# 需要理解的地方:author表是关联到authordetail表中,
# 如果authordetail中删除一条记录,那么author表中的记录也会被删除
# authordetail表属于被关联者
# 总结:表1外键关联到表二,表1删除,不影响表2,表2删除会影响表1

models.Author.objects.get(nid=3).delete()
#这里我删除author表中的数据是不影响到authordetail表的数据,因为是author表关联authordetail表

# 一对多删除:
models.Publish.objects.get(nid=1).delete()
models.Book.objects.get(nid=3).delete()


#多对多删除
book_obj = models.Book.objects.get(nid=2)
book_obj.authors.remove(5)     #删除单个
book_obj.authors.remove(*[5,3])  #删除多个
book_obj.authors.clear()    #全部删除
book_obj.authors.set('3')     #清空完了再设置
book_obj.authors.set(['2','3'])  #清空完了再设置多个作者

orm语句更新数据:


```python
# 更新数据:
    # 多对多的更新
    book_obj = models.Book.objects.get(nid=2)
    book_obj.authors.set(['2', '3'])  # 删除然后更新

    # 一对一的更新:
    obj = models.AuthorDetail.objects.get(nid=2)
    models.Author.objects.filter(nid=2).update(
        name='张胜男',
        age=15,
        authorDetail=models.AuthorDetail.objects.get(nid=10)  #第一种
        authorDetail_id=obj.nid  #第二种
    )
   	# 一对多的更新:
    obj = models.Publish.objects.get(pk=4)  #id可以写成pk  pk=Primary key
    models.Book.objects.filter(pk=6).update(
        title='b哥的往事2',
        publishs=models.Publish.objects.get(nid=3)  #第一种
        publishs_id=obj.nid  #第二种
    )
  # 级联更新:一对一和一对多是一样的
    models.Publish.objects.filter(pk=4).update(
        nid=2,  #没有级联更新 报错  
        #有级联删除但是没有级联更新
        #报错信息:(1451, 'Cannot delete or update a parent row: a foreign key constraint fails (`orm`.`app02_book`, CONSTRAINT `app02_book_publishs_id_2f1300e0_fk_app02_publish_nid` FOREIGN KEY (`publishs_id`) REFERENCES `app02_publish` (`nid`))')

    )

猜你喜欢

转载自blog.csdn.net/qq_39253370/article/details/105170753