博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django的模型层(2)- 多表操作(上)
阅读量:2241 次
发布时间:2019-05-09

本文共 6413 字,大约阅读时间需要 21 分钟。

一、创建模型

       例:我们来假定下面这些概念,字段和关系

              作者模型:一个作者有姓名和年龄。

              作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一(one-to-one)的关系。

              出版社模型:出版社有名称,所在城市以及email。

              书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多(many-to-many)的关联关系; 一本书只应该由一个出版社出版,所以出版社和书籍是一对多(one-to-many)的关系。

       模型建立如下代码:   

from django.db import models        # Create your models here.    class Author(models.Model):        nid = models.AutoField(primary_key=True)        name = models.CharField(max_length=32)        age = models.IntegerField()         # 与AuthorDetail建立一对一的关系,author表自动加authorDetail_id字段        authorDetail = models.OneToOneField(to="AuthorDetail", on_delete=models.CASCADE)    class AuthorDetail(models.Model):        nid = models.AutoField(primary_key=True)        birthday = models.DateField()        telephone = models.BigIntegerField()        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()    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_id        publish = models.ForeignKey(to="Publish", to_field="nid", on_delete=models.CASCADE)        # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表book_authors,且第三张表有book_id和author_id字段        authors = models.ManyToManyField(to='Author',)

       生成表如下图:

       注意事项:

    1)表的名称myapp_modelName,是根据模型中的元数据自动生成的,也可以覆写为别的名称;  

    2)id 字段是自动添加的;

    3)对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名;

    4)这个例子中的CREATE TABLE SQL 语句使用PostgreSQL 语法格式,要注意的是Django 会根据settings 中指定的数据库类型来使用相应的SQL 语句;

    5)定义好模型之后,你需要告诉Django使用这些模型。你要做的就是修改配置文件中的INSTALL_APPSZ中设置,在其中添加models.py所在应用的名称;

    6)外键字段 ForeignKey 有一个参数null=True的设置(它允许外键接受空值 NULL),你可以赋给它空值 None;

二、添加表记录

       操作前先简单的录入一些数据:

       publish表:

       authordetail表:

       author表:

1、一对一

       示例一(添加一条作者信息): 

# 先添加作者详细信息    authorDetail_obj = AuthorDetail.objects.create(tel=tel, addr=addr)    # 再添加作者,因为他依赖AuthorDetail表    Author.objects.create(        name=name,         age=age,         email=email,         authorDetail=authorDetail_obj)
2、一对多(给关联字段所在的表,即book表添加记录)

       方式一:    

publish_obj = Publish.objects.get(nid=1)      book_obj = Book.objects.create(          title="金瓶眉",           publishDate="2012-12-12",           price=100,           publish=publish_obj)   # 对象赋值对象

       方式二:

         
book_obj = Book.objects.create(        title="金瓶眉",         publishDate="2012-12-12",         price=100,         publish_id=1)   # 字段值赋值给字段名

       核心:book_obj.publish与book_obj.publish_id是什么?

3、多对多(核心是给第三张关系表添加记录)

       方式一: 

# book_obj为当前生成的书籍对象    book_obj = Book.objects.create(        title="追风筝的人",         price=200,         publishDate="2012-11-12",         publish_id=1)    # 查询出为书籍绑定的作者对象    yuan = Author.objects.filter(name="yuan").first() # 若yuan在Author表主键是2    egon = Author.objects.filter(name="alex").first() # 若egon在Author表主键是1    # 因Book表与Author表绑定多对多关系,即向关系表book_authors中添加纪录    book_obj.authors.add(yuan, egon) # 将某些特定的 model 对象添加到被关联对象集合

       方式二:

book_obj.authors.add(1, 2) # 直接给新创建的书籍对象绑定两个作者id,即关联表中添加2条记录

       方式三:    

book_obj.authors.add(*[])  # 本质同方式二,位置参数方式传参

       核心:book_obj.authors.all()是什么?

4、补充:多对多关系的其他常用API
book_obj.authors.remove()  # 将某个特定的对象从被关联对象集合中去除    # book_obj.authors.remove(*[])    book_obj.authors.clear()  # 清空被关联对象集合    book_obj.authors.set()  # 先清空再设置 

  例如:

egon_obj = Author.objects.filter(name="egon").first()    book = Book.objects.filter(nid=3).first()    # 解除nid为3的书籍与作者egon的关系,     book.authors.remove(egon_obj) # 即删除第三张表中书籍是3,作者是egon的记录    # 假设已知egon的id为1 ,则可以直接根据id解除关系    book.authors.remove(1)  # 即删除第三张表中book_id是3,author_id是1的记录    # 删除nid=3的书籍的所有作者记录    book.authors.clear()  # 删除book_id为3的所有记录,不管author_id为多少    # 只为nid=3的作者绑定一个id为1的作者    book.authors.set(1)  # 相当于先解除,即clear(),再绑定,即add(1)

      

三、查询表记录

       查询分为:

              跨表查询(基于对象跨表查询、基于双下划线跨表查询);

              聚合查询;

              分组查询;

              F与Q查询;

       正式学习查询之前,我们先来了解一下,什么是正向查询?什么是反向查询?由关联字段所在的表去查询非关联字段所在的表,就是正向查询,反之为反向查询。例如:

              ① 一对多关系,“多”的一方创建关联字段并通过ForeignKey方法建立关联关系,即关联字段所在的表(ForeignKey方法所在的表)去查询另一个表时为正向查询;反之为反向查询。

              ② 多对多关系,任一方创建关联字段并通过ManyToMany方法建立关联关系,即关联字段所在的表(ManyToMany方法所在的表)去查询另一个表时为正向查询;反之为反向查询。

              ③ 一对一关系,任一方通过创建关联字段并通过OneToOne方法建立关联关系,即关联字段所在的表(OneToOne方法所在的表)去查询另一个表时为正向查询;反之为反向查询。

1、基于对象跨表查询(会被翻译成sql子查询)

       1)一对多查询(Publish表与Book表,且Book表为关联字段所在的表)

              a、正向查询(按字段:publish)(多查一)       

# 查询主键为1的书籍的出版社所在城市    book_obj = Book.objects.filter(pk=1).first()    publish_obj = book_obj.publish  # 主键为1的书籍对象关联的出版社对象    print(publish_obj.city)

              b、反向查询(按表名_set:book_set)(一查多)

# 查询苹果出版社出版的所有书籍名称    publish = Publish.objects.get(name="苹果出版社")    book_list = publish.book_set.all() # 与苹果出版社关联的所有书籍对象集合(QuerySet类型)    for book_obj in book_list:      print(book_obj.title)

       2)多对多查询(Author与Book)

              a、正向查询(按字段:authors)

# 查询金瓶眉这本书所有作者的名字以及手机号    book_obj = Book.objects.filter(title="金瓶眉").first()    authors_list = book_obj.authors.all()    for author_obj in authors_list:      print(author_obj.name, author_obj.authorDetail.telephone)

              b、反向查询(按表名_set:book_set)    

# 查询egon写的所有书籍的名字    author_obj = Author.objects.get(name="egon")    book_list = author_obj.book_set.all()  # 与egon作者相关的所有书籍    for book_obj in book_list:        print(book_obj.title)

       3)一对一查询(Author与AuthorDetail)

              a、正向查询(按字段:authorDetail)

# 查询作者egon的手机号码    egon = Author.objects.filter(name="egon").first()    print(egon.authorDetail.telephone)

              b、反向查询(按表名:author)     

# 查询所有住址在北京的作者的姓名    authorDetail_list = AuthorDetail.objects.filter(addr="beijing")    for obj in authorDetail_list:        print(obj.author.name)

注意:你可以通过在ForeignKey()和ManyToManyField()的定义中设置 related_name 的值来覆写“表名_set”的名称。例如,如果 Book表中做以下更改:

publish = models.ForeignKey(Publish, related_name='bookList', on_delete=models.CASCADE)

那么接下来就会如我们看到这般:

# 查询人民出版社出版过的所有书籍    publish_obj=Publish.objects.get(name="人民出版社")    book_list=publish_obj.bookList.all()    # 与人民出版社关联的所有书籍对象集合

 四、补充

1、Foreignkey()用法及参数解释

  ForeignKey(to="Publish", to_field="nid", on_delete=models.CASCADE)方法参数解释

to="Publish":表示跟Publish表建立一对多关系,也可以直接写成"Publish"(需要带引号,不带引号则models.py中建立表时有顺序要求,即关联表Publish在前边);    to_field="nid":跟关联表(这里是Publish表)的哪个字段建立联系,此参数不写则默认跟主键字段建立联系;    on_delete=models.CASCADE:级联删除(即同步删除,同步更新),Django1.11版本默认就是级联删除,可不写,但2版本要求必须写,否则报错;   注意:级联删除表示删除主表记录,从表(ForeignKey所在表)对应记录也会自动删除;而删除从表记录,主表记录不会自动删除。

 

转载于:https://www.cnblogs.com/li-li/p/9848508.html

你可能感兴趣的文章
【JS】【31】读取json文件
查看>>
OpenSSL源代码学习[转]
查看>>
google app api相关(商用)
查看>>
linux放音乐cd
查看>>
GridView+存储过程实现'真分页'
查看>>
flask_migrate
查看>>
解决activemq多消费者并发处理
查看>>
UDP连接和TCP连接的异同
查看>>
hibernate 时间段查询
查看>>
java操作cookie 实现两周内自动登录
查看>>
Tomcat 7优化前及优化后的性能对比
查看>>
Java Guava中的函数式编程讲解
查看>>
Eclipse Memory Analyzer 使用技巧
查看>>
tomcat连接超时
查看>>
谈谈编程思想
查看>>
iOS MapKit导航及地理转码辅助类
查看>>
检测iOS的网络可用性并打开网络设置
查看>>
简单封装FMDB操作sqlite的模板
查看>>
iOS开发中Instruments的用法
查看>>
强引用 软引用 弱引用 虚引用
查看>>