环境:

根据关系创建表

首先建立django项目,编辑models.py 文件

models.py

fromdjango.dbimportmodels#Createyourmodelshere.classPublish(models.Model):#id如果不写,会自动生成,名字叫做nid,并且自增#数据库不同,可能自动生成的id名字也不太一样。id=models.AutoField(primary_key=True)name=models.CharField(max_length=32)addr=models.CharField(max_length=64)email=models.EmailField()classAuthor_details(models.Model):phone=models.CharField(max_length=16)sex=models.IntegerFieldclassAuthor(models.Model):name=models.CharField(max_length=32)addr=models.CharField(max_length=64)#使用了OneToOneField与ForeignKey,模型表的字段,后面会自动加_id#一对一的关系:OneToOneFieldauthordetail_id=models.OneToOneField(to='Author_details',to_field='id')def__str__(self):returnself.nameclassBook(models.Model):name=models.CharField(max_length=16)#浮点型,共5位,小数部分是2位price=models.DecimalField(max_digits=5,decimal_places=2)#to=关联表to_field=关联表中的字段,一对多的关系使用ForeignKeypublish=models.ForeignKey(to=Publish,to_field='id')#ManyToManyField会自动创建第三张表多对多的关系authors=models.ManyToManyField(to=Author)def__str__(self):returnself.name

迁移数据库

makemigrations

migrate

在项目中创建Py文件,可以运行在django环境中的代码

test.py

importosif__name__=='__main__':os.environ.setdefault("DJANGO_SETTINGS_MODULE","pro77_13.settings")importdjangodjango.setup()fromapp01.modelsimport*

一、多表模型创建,一对多的增删改,与多对多增删改

在app01_publish表中添加几条数据

一对多新增数据(接上面的继续写)

test.py

#添加一本北京出版社出版的书#第一种方式#ret=Book.objects.create(name='红楼梦',price=53.4,publish_id=1)#print(ret.name)#第二种方式,存对象Publish=出版社对象,存到数据库是一个id#pk:主键,是通过主键查找publish=Publish.objects.filter(pk=2).first()ret=Book.objects.create(name='红楼梦',price=53.4,publish=publish)print(ret.name)

app01_book表

# 一对多修改数据

test.py

方式一:

book=Book.objects.get(pk=1)#解释:book.publish=出版社对象book.publish_id=2book.save()

app01_book表:

方式二:

#解释:book=Book.objects.filter(pk=1).update(publish=出版社对象)book=Book.objects.filter(pk=1).update(publish_id=1)

app01_book表:


多对多新增数据

首先需要在app01_author与app01_author_details表中添加数据

app01_author_details表:

app01_author表:


test.py

# 为红楼梦这本书新增一个叫lqz,egon的作者

方式一:

test.py

lqz=Author.objects.filter(name='lqz').first()egon=Author.objects.filter(name='egon').first()book=Book.objects.filter(name='红楼梦').first()##add添加多个对象book.authors.add(lqz,egon)

这样就可以在中间表里看见(app01_book_authors:中间表)

方式二:

#add添加作者idbook.authors.add(1,2)

# 删除 remove,可以传对象,可以传id,可以传多个,不要混着用

lqz=Author.objects.filter(name='lqz').first()egon=Author.objects.filter(name='egon').first()book=Book.objects.filter(name='红楼梦').first()book.authors.remove(lqz)#也可以#book.authors.remove(1,2)#clear清空所有#book.authors.clear()

set,要传一个列表,列表内可以是 id,也可以是对象

book.authors.set([2,])#book.authors.set([lqz,])

app01_book_authors表


总结:

1 创建多表模型(详情见代码)
#用了OneToOneField和ForeignKey,模型表的字段,后面会自定加_id
# ManyToManyField会自动创建第三张表
# *************重点
# 一对一的关系:OneToOneField
# 一对多的关系:ForeignKey
# 多对多的关系:ManyToManyField

2 添加表记录
1 一对多新增
-两种方式:
-publish=对象
-publish_id=id
2 一对多删除:同单表删除
3 一对多修改:两种方式,可以传对象,可以传id
4 一对一跟一对多一样
5 多对多:
-add ----->可以传对象,可以传id,可以传多个
-remove ----->可以传对象,可以传id,可以传多个
-clear ---->没有参数
-set ----->跟上面不一样,必须传列表,列表里面可以是对象,可以是id

二、基于对象的跨表查询

一对一:
正向 author---关联字段在author--->authordetail ------> 按字段
反向 authordetail------关联字段在author--->author -----> 按表名小写

正向查询:

lqz=Author.objects.filter(name='lqz').first()egon=Author.objects.filter(name='egon').first()book=Book.objects.filter(name='红楼梦').first()#查询lqz作者的手机号正向查询#author=Author.objects.filter(name='lqz').first()#authordetail=author.authordetail_id#print(authordetail.phone)

反向查询:

lqz=Author.objects.filter(name='lqz').first()egon=Author.objects.filter(name='egon').first()book=Book.objects.filter(name='红楼梦').first()#查询地址是:手机号属于哪位作者的反向查询authordetail=Author_details.objects.filter(phone='1385469823').first()author=authordetail.authorprint(author.name)

一对多:

正向 book---关联字段在book--->publish ------> 按字段
反向 publish------关联字段在book--->book -----> 按表名小写_set.all()

正向查询:查询红楼梦这本书的出版社邮箱

book=Book.objects.filter(name='红楼梦').first()##book.publish就是出版社对象publish=book.publishprint(publish.email)

反向查询:查询地址是北京 的出版社出版的图

publish=Publish.objects.filter(addr='北京').first()##publish.book_set.all()拿出所有的图书#books=publish.book_set.all()##统计一下条数books=publish.book_set.all().count()print(books)

多对多:

正向 book---关联字段在book--->author ------> 按字段.all()
反向 author------关联字段在book--->book -----> 按表名小写_set.all()

正向:查询红楼梦这本书所有的作者

book=Book.objects.filter(name='红楼梦').first()book.authors.all()#是所有的作者,是一个queryset对象,可以继续点print(book.authors.all())

反向:查询lqz写的所有书

lqz=Author.objects.filter(name='lqz').first()books=lqz.book_set.all()print(books)

连续跨表
# 查询红楼梦这本书所有的作者的手机号

book=Book.objects.filter(name='红楼梦').first()authors=book.authors.all()forauthorinauthors:authordetail=author.authordetail_idprint(authordetail.phone)

# 基于对象的查询---是子查询也就是多次查询

在终端打印出sql语句

需要要settings.py中配置以下内容

LOGGING={'version':1,'disable_existing_loggers':False,'handlers':{'console':{'level':'DEBUG','class':'logging.StreamHandler',},},'loggers':{'django.db.backends':{'handlers':['console'],'propagate':True,'level':'DEBUG',},}}

test.py

book=Book.objects.filter(name='红楼梦').first()

对应的sql语句:

SELECT`app01_book`.`id`,`app01_book`.`name`,`app01_book`.`price`,`app01_book`.`publish_id`FROM`app01_book`WHERE`app01_book`.`name`='红楼梦'ORDERBY`app01_book`.`id`ASCLIMIT1;

在查询结果之后的又一次查询(子查询,也就是多次查询)

print(book.authors.all())

对应的sql语句:

SELECT`app01_author`.`id`,`app01_author`.`name`,`app01_author`.`addr`,`app01_author`.`authordetail_id_id`FROM`app01_author`INNERJOIN`app01_book_authors`ON(`app01_author`.`id`=`app01_book_authors`.`author_id`)WHERE`app01_book_authors`.`book_id`=1LIMIT21;

总结:

基于对象的跨表查询
1 一对一
正向:正向查询按字段
反向:反向查询按表名小写
2 一对多
正向:正向查询按字段
反向:反向按表名小写_set.all()
3 多对多
正向:正向查询按字段
反向查询:反向按表名小写_set.all()
4******基于对象的查询,多次查询(子查询)

# 基于双下划线的查询

# 一对一
# 查询lqz作者的手机号 正向查询 跨表的话,按字段
# 以author表作为基表

ret=Author.objects.filter(name='lqz').values('authordetail_id__phone')print(ret)

# 以authordetail作为基表 反向查询,按表名小写 跨表的话,用表名小写

ret=Author_details.objects.filter(author__name='lqz').values('phone')print(ret)

# 查询lqz这个作者的手机号
# 正向

ret=Author.objects.filter(name='lqz').values('authordetail_id__phone')print(ret)

#查询手机号是 1529874130 的作者

ret=Author.objects.filter(authordetail_id__phone='1529874130')print(ret)ret=Author_details.objects.filter(phone='1529874130')print(ret)