Django多表查询

1 创建多表模型(详情见代码)
		#用了OneToOneField和ForeignKey,模型表的字段,后面会自定加_id
		# ManyToManyField会自动创建第三张表
		# *************重点
		# 一对一的关系:OneToOneField
		# 一对多的关系:ForeignKey
		# 多对多的关系:ManyToManyField
	-OneToOneField ---一对一 
		-ForeignKey----一对多
			-级联删除CASCADE
			-设置为空:SET_NULL
			-什么都不做:DO_NOTHING
			ForeignKey(to=Publish, to_field='id',on_delete=models.CASCADE) #Django 2.0必须设置on_delete的状态 因为1.0的版本都是自动是外键关联,级联删除
		-ManyToManyField ------>多对多(自动创建第三张表)
		-AutoField(primary_key=True)
		-CharField
		-EmailField
2 添加表记录 1 一对多新增 -两种方式: -publish=对象 -publish_id=id 2 一对多删除:同单表删除 3 一对多修改:两种方式,可以传对象,可以传id 4 一对一跟一对多一样 5 多对多: -add ----->可以传对象,可以传id,可以传多个 -remove ----->可以传对象,可以传id,可以传多个 -clear ---->没有参数 -set ----->跟上面不一样,必须传列表,列表里面可以是对象,可以是id 3 基于对象的跨表查询 1 一对一 正向:正向查询按字段 反向:反向查询按表名小写 2 一对多 正向:正向查询按字段 反向:反向按表名小写_set.all() 3 多对多 正向:正向查询按字段 反向查询:反向按表名小写_set.all() 4******基于对象的查询,多次查询(子查询)  基于双下划线的跨表查询 -连表查询 -一对一双下划线查询 -正向:按字段,跨表可以在filter,也可以在values中 -反向:按表名小写,跨表可以在filter,也可以在values中

m
o
d
e
l
e
s
文件

from django.db import models


# Create your models here.

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


class Publish(models.Model):
# id如果不写,会自动生成,名字叫nid,并且自增
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64)
email = models.EmailField()


class Author(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
# 数字类型
sex = models.IntegerField()
# 可以用ForeignKey,但是得设置唯一性约束,会报警告,不建议用,建议用OneToOneField
# authordetail=models.ForeignKey(unique=True)
# to='AuthorDetail' 加引号,这个表能找到就可以,不用引号,类必须在上面定义
authordetail = models.OneToOneField(to='AuthorDetail', to_field='id')

def __str__(self):
return self.name


class AuthorDetail(models.Model):
id = models.AutoField(primary_key=True)
phone = models.CharField(max_length=32)
addr = models.CharField(max_length=64)


class Book(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish = models.ForeignKey(to=Publish, to_field='id')

authors = models.ManyToManyField(to=Author)
def __str__(self):
return self.name

test文件中
import os

if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day77.settings")
import django

django.setup()

from app01.models import *

# 一对多新增数据
# 添加一本北京出版社出版的书
# 第一种方式
# ret=Book.objects.create(name='红楼梦',price=34.5,publish_id=1)
# print(ret.name)
# 第二种方式,存对象publish=出版社的对象,存到数据库,是一个id
# publish=Publish.objects.get(id=1)
# pk是主键,通过主键查找
# publish=Publish.objects.get(pk=1)
# publish = Publish.objects.filter(pk=2).first()
# ret = Book.objects.create(name='西游记', price=34.5, publish=publish)
# print(ret.name)
# 一对多修改数据
# book=Book.objects.get(pk=1)
# # book.publish=出版社对象
# book.publish_id=2
# book.save()
# 方式二
# book=Book.objects.filter(pk=1).update(publish=出版社对象)
# book=Book.objects.filter(pk=1).update(publish_id=1)
# 多对多新增
# 为红楼梦这本书新增一个叫lqz,egon的作者
# 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)
# add添加作者id
# book.authors.add(1,2)
#删除 remove,可以传对象,可以传id,可以传多个,不要混着用
# book.authors.remove(lqz)
# book.authors.remove(2)
# book.authors.remove(1,2)
# clear清空所有
# book.authors.clear()
# set,先清空,在新增,要传一个列表,列表内可以是, id,也可以是对象
# book.authors.set([lqz,])
# ********这样不行,因为它打散了传过去了,相当于book.authors.set(lqz)
# book.authors.set(*[lqz,])


# lqz=Author.objects.filter(name='lqz')
# print(type(lqz))
from django.db.models.query import QuerySet
# ***************************基于对象的跨表查询
'''
一对一
正向 author---关联字段在author--->authordetail ------> 按字段
反向 authordetail------关联字段在author--->author -----> 按表名小写

'''
# 查询lqz作者的手机号 正向查询
# author=Author.objects.filter(name='lqz').first()
# # author.authordetail 就是作者详情的对象
# authordetail=author.authordetail
# print(authordetail.phone)
# 查询地址是 :山东 的作者名字 反向查询
# authordetail=AuthorDetail.objects.filter(addr='山东').first()
# # authordetail.author 这是作者对象
# author=authordetail.author
# print(author.name)

#一对多
'''
一对多
正向 book---关联字段在book--->publish ------> 按字段
反向 publish------关联字段在book--->book -----> 按表名小写_set.all()
'''
# 正向 查询红楼梦这本书的出版社邮箱
# book=Book.objects.filter(name='红楼梦').first()
# # book.publish 就是出版社对象
# pulish=book.publish
# print(pulish.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()
# for author in authors:
# authordetail=author.authordetail
# print(authordetail.phone)


# ****************************基于对象的查询---是子查询也就是多次查询
# ***************基于双下划线的查询*****
# 一对一
# 查询lqz作者的手机号 正向查询 跨表的话,按字段
# 以author表作为基表
# ret=Author.objects.filter(name='lqz').values('authordetail__phone')
# print(ret)
# 以authordetail作为基表 反向查询,按表名小写 跨表的话,用表名小写
# ret=AuthorDetail.objects.filter(author__name='lqz').values('phone')
# print(ret)
# 查询lqz这个作者的性别和手机号
# 正向
# ret=Author.objects.filter(name='lqz').values('sex','authordetail__phone')
# print(ret)
# 查询手机号是13888888的作者性别
# ret=Author.objects.filter(authordetail__phone='13888888').values('sex')
# print(ret)
# ret=AuthorDetail.objects.filter(phone='13888888').values('author__sex')
# print(ret)
 
 
posted @ 2018-11-13 15:35  不沉之月  阅读(217)  评论(0编辑  收藏  举报