django 关系映射
常见的关系映射有一对一(一张身份证对应一个人)、一对多(一个班级可以有多个学生)、多对多(一个学生报多门课,一门课供多名学生学习)等
-
一对一映射:
-
语法:OneToOneField(类名,on_delete=xxx)
-
创建表:
class Author(model.Model): ... class Wife(model.Model): author=models.OneToOneField(Author,on_delete=xxx) #on_delete表示级联删除,有多个可供选择的参数(models.CASCADE共存亡、models.PROTECT保护模式,不准删)
-
创建数据:
-
无外键的模型类(Author):
author1 = Author.objects.create(name='王老师')
-
有外键的模型类(Wife):用外键的字段名/用外键的类属性名。
wife1 = Wife.objects.create(name='王夫人',author=author1) #"author"是类属性名,关联的是王老师这个obj,即Author的一个实例化的对象 wife1 = Wife.objects.create(name='王夫人',author_id=1) #"author_id"是外键字段名,关联的是王老师这个对象的一个主键值
-
-
查询数据:有两者其中一个数据,怎么通过这个查找另一个。
-
正向查询:直接通过外键属性查询。例如:通过wife找author,
from .models import wife wife = wife.objects.get(name='wangfuren') print(wife.name,'的老公是',wife.author.name)
-
反向查询:没有外键属性的一方,可以调用反向属性查询到关联的另一方,反向关联属性为‘实例对象.引用类名(小写)’,如作假的反向引用为‘作家对象.wife’
author1 = Author.objects.get(name='wang') print(author1.wife.name) #当反向引用不存在时,就会报错
-
-
-
一对多映射:
一对多需要明确出具体的角色,在多这个角色的表上设置外键。当一个A类对象可以关联多个B类对象时:-
语法:
models.ForeignKey('一'对应的模型类,on_delete=xx),必须指明on_delete的模式
-
创建表:
class A(model.Model):... class B(model.Model): 属性 =models.ForeignKey("一"对应的模型类,on_delete=xx)
-
创建数据:先创建‘一’,再创建‘多’。
from .models import * pub1 = Publisher.objects.create(name='清华大学出版社') #无外键的模型类 book1 = Book.objects.create(title='C++',publisher=pub1) #用外键的类属性名进行关联,关联的是该模型类的一个实例化对象 book2 = Book.objects.create(title='Java',publisher_id=1) #用外键的字段名进行关联,关联的是外表中该字段的主键的值
-
查询数据:
-
正向查询:
【通过Book查询Publisher】(写有外键的那个 查 没有外键的那个),例如通过publisher属性进行查询:abook = Book.objects.get(id=1) print(abook.title,"的出版社是:",abook.publisher.name)
-
反向查询:
【通过Publisher查询对应的所有的Book】,需要用到反向属性#通过出版社查询对应的书 pub1 = Publisher.objects.get(name='清华大学出版社') book = pub1.book_set.all() #通过book_set获取pub1对应的多个Book数据对象 ;类名(小写)_set #books = Book.objects.filter(publisher=pub1) #也可以采用这种方式获取 print("清华大学出版社的书有:") for book in books: print(book.title)
-
-
-
多对多映射:
mysql中创建多对多需要依赖第三张表来实现,Django中无需手动创建第三张表,Django自动完成。例如一个作者可以出版多本书,一本书可以被多名作者同时编写。-
语法:在关联的两个类中的任意一个类中,添加:属性=models.ManyToManyField(MyModel)
-
创建表:
class Author(models.Model):... class Book(models.Model): authors = models.ManyToManyField(Author)
-
创建数据:
-
方案1:先创建author,再关联book;
author1 = Author.objects.create(name='吕老师') author2 = Author.objects.create(name='王老师') #吕老师和王老师同时写了一本书Python book1 = author1.book_set.create(title="Python") #用Author的反向属性创建Book对象,相当于创建了一本书,同时和author1绑定起来,(相当于先创建了一本书,再绑上) author2.book_set.add(book1) #相当于已经有了一本书,直接绑定
-
方案2:先创建book,再关联author
book = Book.objects.create(title="Django") #kevin和吕老师都参与了Django这本书的创作 author3 = book.authors.create(name = 'kevin') #authors是Book中的多对多属性,这相当于创建了一个author,再和书进行绑定 book.authors.add(author1) #这相当于已经有了这本书,再和作者绑定
-
-
查询数据:
-
正向查询:
有多对多属性的对象查另一方,也就是通过Book查询对应的所有的Author,此时多对多属性等价于objects。book.authors.all() 是获取book对应的所有的author的信息 book.authors.filter(age__lt=80) 是获取book对应的作者中年龄小于80的作者的信息
-
反向查询:
通过Author查询对应的所有的Book,利用反向属性book_setauthor.book_set.all() author.book_set.filter()
-
-