一对一
author = models.OneToOneField('authorDetail',on_delete=models.CASCADE)
# on_delete级联删除,一方删除,另一方也跟着删除,django2.0版本以下默认有级联删除属性
一对多
publishs=models.ForeignKey(to="Publish",on_delete=models.CASCADE,)
多对多
authors = models.ManyToManyField('author',)
# 多对多时,不需要自己创建类,会默认创建
关于on_delete
on_delete
当删除关联表中的数据时,当前表与其关联的行的行为。
models.CASCADE
删除关联数据,与之关联也删除
models.DO_NOTHING
删除关联数据,引发错误IntegrityError
models.PROTECT
删除关联数据,引发错误ProtectedError
models.SET_NULL
删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
models.SET_DEFAULT
删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
models.SET
删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
ForeignKey的db_contraint参数
关系和约束大家要搞清楚,我不加外键能不能表示两个表之间的关系啊,当然可以
但是我们就不能使用ORM外键相关的方法了,所以我们单纯的将外键换成一个其他字段类型,只是单纯的存着另外一个关联表的主键值是不能使用ORM外键方法的。
#db_constraint=False只加两者的关系,没有强制约束的效果,并且ORM外键相关的接口(方法)还能使用,所以如果将来公司让你建立外键,并且不能有强制的约束关系,那么就可以将这个参数改为False
customer = models.ForeignKey(verbose_name='关联客户', to='Customer',db_constraint=False)
添加表记录
一对多
from app01.models import Book
方式1:
publish_obj = Publish.objects.get(nid=1) # 拿到nid为1的出版社对象
book_obj=Book.objects.create(title='活着',publishDate='2018-12-12',price=100,publish=publish_obj)
# 出版社对象作为值publish,其实就是自动将publish字段变成publish_id,然后将publish_obj的id取出来赋值给publish_id字段,注意,如果不是publish类的对象肯定会报错的
方式2:
book_obj=Book.objects.create(title='活着‘,publishDate='1028-12-12',price=100,publish_id=1)
# 直接可以写id值,注意这个是publish_id,是数据库里的字段
多对多
方式一: 多对多一般在前端页面上使用的时候是多选下拉框的样子来给用户选择多个数据,这里可以让用户选择多个书籍,多个作者
# 当前生成的书籍对象
book_obj=Book.objects.create(title="追风筝的人",price=200,publishDate="2012-11-12",publish_id=1)
# 为书籍绑定的做作者对象
yuan=Author.objects.filter(name="admin").first() # 在Author表中主键为2的纪录,注意取的是author的model对象
egon=Author.objects.filter(name="test").first() # 在Author表中主键为1的纪录
#有人可能会说,我们可以直接给第三张表添加数据啊,这个自动生成的第三张表你能通过models获取到吗,是获取不到的,用不了的,当然如果你知道了这个表的名字,那么你通过原生sql语句可以进行书的添加,所以要通过orm间接的给第三张表添加数据,如果是你手动添加的第三张表你是可以直接给第三张表添加数据
# 绑定多对多关系,即向关系表book_authors中添加纪录,给书添加两个作者,下面的语法就是告诉orm给第三张表添加两条数据
book_obj.authors.add(yuan,egon) # 将某些特定的 model 对象添加到被关联对象集合中。 ======= book_obj.authors.add(*[])
#book_obj是书籍对象,authors是book表里面那个多对多的关系字段名称。
#其实orm就是先通过book_obj的authors属性找到第三张表,然后将book_obj的id值和两个作者对象的id值组合成两条记录添加到第三张表里面去
方式二
book_obj.authors.add(1,2)
book_obj.authors.add(*[1,2]) #这种方式用的最多,因为一般是给用户来选择,用户选择是多选的,选完给你发送过来的就是一堆的id值
多对多关系其它常用API
book_obj.authors.remove() # 将某个特定的对象从被关联对象集合中去除。 ====== book_obj.authors.remove(*[1,2]),将多对多的关系数据删除
book_obj.authors.clear() #清空被关联对象集合
book_obj.authors.set() #先清空再设置 =====
删除实例:
book_obj = models.Book.objects.filter(nid=4)[0]
# book_obj.authors.remove(2) #将第三张表中的这个book_obj对象对应的那个作者id为2的那条记录删除
# book_obj.authors.clear()
# book_obj.authors.set('2') #先清除掉所有的关系数据,然后只给这个书对象绑定这个id为2的作者,所以只剩下一条记录 3---2,比如用户编辑数据的时候,选择作者发生了变化,那么需要重新选择,所以我们就可以先清空,然后再重新绑定关系数据,注意这里写的是字符串,数字类型不可以
book_obj.authors.set(['1',]) #这么写也可以,但是注意列表中的元素是字符串,列表前面没有*,之前我测试有*,感觉是版本的问题,没事,能够用哪个用哪个
一对一
更新:
book_obj = models.Book.objects.get(id=1) #获取一个书籍对象
data = {'title':'xxx','price':100} #这个书籍对象更新后的数据
models.Book.objects.filter(id=n).update(**data) #将新数据更新到原来的记录中
book_obj.authors.set(author_list) #将数据和作者的多对多关系加上
删除:
models.Book.objects.filter(id=1).delete() 级联删除
基于对象的跨表查询
一对一
关系属性写在表1,关联到表2,那么通过表1的数据去找表2的数据,叫做正向查询,返过来就是反向查询
数据:
from django.db import models
# Create your models here.
class Author(models.Model):
"""
作者表
"""
name=models.CharField( max_length=32)
age=models.IntegerField()
# authorDetail=models.OneToOneField(to="AuthorDetail",to_field="nid",on_delete=models.CASCADE) #
au=models.OneToOneField("AuthorDetail",on_delete=models.CASCADE)
class AuthorDetail(models.Model):
"""
作者详细信息表
"""
birthday=models.DateField()
telephone=models.CharField(max_length=11)
addr=models.CharField(max_length=64)
# class Meta:
# db_table='authordetail' #指定表名
# ordering = ['-id',]
class Publish(models.Model):
"""
出版社表
"""
name=models.CharField( max_length=32)
city=models.CharField( max_length=32)
class Book(models.Model):
"""
书籍表
"""
title = models.CharField( max_length=32)
publishDate=models.DateField()
price=models.DecimalField(max_digits=5,decimal_places=2)
publishs=models.ForeignKey(to="Publish",on_delete=models.CASCADE,)
authors=models.ManyToManyField('Author',)
查一下root的电话号码
正向查询 对象.属性
obj = models.Author.objects.filter(name=‘root’).first()
ph = obj.au.telephone
print(ph)
查一下电话号码为120的作者姓名
反向查询 对象.小写的表名
obj = models.AuthorDetail.ojbects.filter(telephone=120).first()
ret = obj.author.name – admin
print(ret)
一对多
查一下 活着这本书是哪个出版社出版的?
正向查询
obj = models.Book.objects.filter(title=‘活着’).first()
ret = obj.publish.name
print(ret)
查一下北京电子出版社出版过哪些书?
反向查询
obj = models.Publish.objects.filter(name=‘北京电子出版社’).first()
ret = obj.book_set.all()
#–<QuerySet [<Book: 母猪的产后护理>, <Book: 王富贵的怂逼人生>]>
for i in ret:
print(i.title)
多对多
王富贵的怂逼人生 是哪些作者写的 – 正向查询
obj = models.Book.objects.filter(title=‘王富贵的怂逼人生’).first()
ret = obj.authors.all() # 不止一个
for i in ret:
print(i.name)
查询一下余华写了哪些书籍? – 反向查询
obj = models.Author.objects.filter(name=‘余华’).first()
ret = objects.book_set.all()
print(ret)
for i in ret:
print(i.publishs.name)
print(i.title)
OVER~~