一、创建模型

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

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

作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一(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()是什么?

3、补充:多对多关系的其他常用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)
 

more>>

三、查询表记录

查询分为:

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

聚合查询;

分组查询;

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、反向查询(按表名: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、反向查询(按表名: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=Publish.objects.get(name="人民出版社")
book_list=publish.bookList.all() # 与人民出版社关联的所有书籍对象集合

四、补充

1、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所在表)对应记录也会自动删除;而删除从表记录,主表记录不会自动删除。
 

ORM多表操作上的更多相关文章

  1. Django框架05 /orm单表操作

    Django框架05 /orm单表操作 目录 Django框架05 /orm单表操作 1. orm使用流程 2. orm字段 3. orm参数 4. orm单表简单增/删/改 5. orm单表查询 5 ...

  2. Django ORM 多表操作

    目录 Django ORM 多表操作 表模型 表关系 创建模型 逆向到表模型 插入数据 ORM 添加数据(添加外键) 一对多(外键 ForeignKey) 一对一 (OneToOneFeild) 多对 ...

  3. day59——orm单表操作

    day59 orm单表操作 对象关系映射(object relational mapping) orm语句 -- sql -- 调用pymysql客户端发送sql -- mysql服务端接收到指令并执 ...

  4. 17-2 orm单表操作和多表操作

    参考:https://www.cnblogs.com/liwenzhou/p/8660826.html 一  ORM单表操作 1 增删改查 1. 查询 1. 查所有 models.Publisher. ...

  5. Django框架06 /orm多表操作

    Django框架06 /orm多表操作 目录 Django框架06 /orm多表操作 1. admin相关操作 2. 创建模型 3. 增加 4. 删除 5. 修改 6. 基于对象的跨表查询 7. 基于 ...

  6. day53:django:URL别名/反向解析&URL分发&命名空间&ORM多表操作修改/查询

    目录 1.URL别名&反向解析 2.URL分发&命名空间 3.ORM多表操作-修改 4.ORM多表操作-查询 4.1 基于对象的跨表查询 4.2 基于双下划线的跨表查询 4.3 聚合查 ...

  7. Django ORM多表操作

    多表操作 创建模型 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对 ...

  8. ORM 多表操作查询及增删改查

    ------------------------------------------只有对前途乐观的人,才能不怕黑暗,才能有力量去创造光明.乐观不是目的,而是人生旅途中的一种态度. 多表操作 创建模型 ...

  9. 09 ORM 多表操作,创建表,添加记录

    1.数据库表关系 1.一对多 为什么需要,重复字段太多 一对多关系表 Book id title price publish_id 1 python 100 1 2 php 200 2 3 go 10 ...

随机推荐

  1. 克隆虚拟机启动网卡提示错误 Device eth0 does not seem to be present, delaying initialization

    错误原因: 克隆的Linux系统在新的机器上运行,新服务器网卡物理地址已经改变.而/etc/udev/rules.d/70-persistent-net.rules这个文件确定了网卡和MAC地址的信息 ...

  2. customizable route planning 工业界地图产品的路径规划

    https://www.microsoft.com/en-us/research/publication/customizable-route-planning/?from=http%3A%2F%2F ...

  3. sublime 3 安装格式化JSON插件

    转自 https://blog.csdn.net/sweettool/article/details/72677784     一.首先下载SublimePrettyJson插件包 https://g ...

  4. 004-unity3d MonoBehaviour脚本方法简介

    一.MonoBehaviour 1.公共方法 CancelInvoke Cancels all Invoke calls on this MonoBehaviour. Invoke Invokes t ...

  5. 002-js-cookie

    cookie操作方法 1.写cookie //JS操作cookies方法! //写cookies function setCookie(name,value) { var Days = 30; var ...

  6. log4j 不输出mybatis的sql

    有可能导入多个日志工具jar,导致mybatis不知道使用哪种日志.修改你的mybatis配置,添加setting,指定日志类型为log4j. <configuration> <!- ...

  7. beanstalkd 安装和配置

    安装 安装以centos为例 yum install beanstalkd 配置 使用centos yum安装,通过查看服务脚本发现有这个配置文件 cat /etc/sysconfig/beansta ...

  8. vue集成汉字转拼音或提取首字母

    需求:             有时我们为了节省用户的维护量,需要根据中文生成出相应的拼音和缩写 解决:            此方法是利用汉字和Unicode编码对应找到相应字母 一.编写汉字和编码 ...

  9. 解决ajax跨域几种方式

    发生跨域问题的原因: 浏览器的限制,出于安全考虑.前台可以正常访问后台,浏览器多管闲事报跨域问题,但其实前台已经访问到后台了. 跨域,协议.域名.端口任何一个不一样浏览器就认为是跨域. XHR(XML ...

  10. 使用MySQL Workbench进行数据库设计——MySQL Workbench使用方法总结

    本文出自[我是干勾鱼的博客] 转自:https://blog.csdn.net/dongdong9223/article/details/48318877 1 创建Model(设计ER图) 使用wor ...