django ORM中的表关系

多对一:
  为了方便理解,两个表之间使用ForeignKey连接时,使用ForeignKey的字段所在的表为从表,被ForeignKey连接的表为主表。

  使用场景:书和出版社之间的关系,一本书只能由一个出版社出版,一个出版社却可以出版很多书

  实现方式:一对多或者说多对一,在Django中是使用ForeignKey实现的,下面是例子:
    class Publisher(models.Model):
      id = models.AutoField(primary_key=True)
      name = models.CharField(max_length=64,blank=True)
      mobile = models.CharField(max_length=11,unique=True)

    class Book(models.Model):
      name = models.CharField(max_length=64,blank=True)
      content = models.TextField(blank=True)
      pub_time = models.DateTimeField(auto_now_add=True)
      publisher = models.ForeignKey(Publisher,on_delete=models.SET_NULL,null=True,related_name=‘book‘,related_query_name=‘books‘)

  详解:表中使用ForeignKey时,从表中会生成(该字段名+_id)的字段,该示例中在Book表中会生成publisher_id的字段,而在主表中则会默认的为我们添加一个(从表名小写+_set的属性),该属性是一个类似于objects的ReleatedManager对象,在该示例中默认应该是生成一个book_set的ReleatedManager对象,如果我们想要使用其他的名字代替(从表名小写+_set),我们需要在从表中使用ForeignKey的时候传递一个related_name参数,以后这个参数的值就会代替(从表名小写+_set),并且拥有其的所有属性和方法

  外键之添加数据:
    1、从表中使用ForeignKey的字段传递主表的一行对象或者该字段名+_id传递主表中对应数据对象的id值:
      publisher = Publisher(name=‘北京大学出版社‘,mobile=‘13395676110‘)
      publisher.save()
      book = Book(name=‘三国‘,content=‘东汉末年群雄争霸的故事‘)
      book.publisher = publisher
      book.save()

    2、使用add函数,把从表中的一条或多条数据添加到主表中的一条数据中,此时会用的related_name的值:
      publisher = Publisher(name=‘安徽出版社‘,mobile=‘16665678912‘,email=‘[email protected]‘)
      publisher.save()
      book = Book(name=‘梁祝‘,content=‘梁山伯与祝英台的爱情故事‘)
      publisher.book.add(book,bulk=False) # 注意bulk参数的使用,当设置为FALSE时,操作时从表的数据不需要执行save(),这也是为了避免从表中使用ForeignKey字段不允许为空与现实之间的矛盾,此函数会为我们自动执行。

  多对一之查询:
    已知从表中的数据,查询主表中的数据,在此例中就是已知图书,查询这本书的出版社,其实这个时候就像操作查询类实例的属性一样操作就行了:
      book = Book.objects.filter(pk=2).first()
      print(book.publisher)

    已知主表中的一条数据,查询出从表使用外键与之关联的所有数据,这时候我们就应该使用(从表名小写+_set)这个RelatedManager对象进行查询,注意这个对象可以使用filter,first等函数,当然这个对象在传递related_name参数简写,此例中使用这种简写方式:
      publisher = Publisher.objects.filter(pk=2).first()
      books = publisher.book.all() # 原生的应该是books = publisher.book_set.all()
      for book in books:
        print(book)

一对一
  同样,为了方便理解,我么设定使用OneToOneField字段所在的表为从表,OneToOneField字段连接的表为主表

  使用场景:一般网站做用户信息统计的时候,通常会做两张表,一张存储常用信息,一张存储不常用的信息,这样做的目的也是为了查询的效率,此时这两张表就是一对一的关系

  实现方式:在django中实现表与表之间的一对一关系使用的是OneToOneField,其实这个OneToOneField本质上讲就是ForeignKey,只不过在外键的基础上,使用该外键的字段增加了unique唯一约束:
    class User(models.Model):
      name = models.CharField(max_length=64)
      password = models.CharField(max_length=64)
      age = models.PositiveSmallIntegerField()

    class UserExtra(models.Model):
      user = models.OneToOneField(User,on_delete=models.CASCADE,related_name=‘extra‘)
      birthday = models.DateField()
      address = models.CharField(max_length=128)

  详解:在使用OneToOneField时,在从表中会生成一个该字段名+_id的字段,如user_id,而在主表中则会生成一个从表名小写的属性,用来关联从表中的相关数据,如userextra。当然在OneToOneField中你也可以传递一个related_name的参数,如‘extra‘,这时候主表中数据就可以使用该参数的值去关联从表中的相关数据。

  一对一之添加数据:
    从表中使用OneToOneField的字段传递主表的一行对象或者该字段名+_id传递主表中对应数据对象的id值,其实操作就像是类对象设置保存属性一样:
      user = User(name=‘李毛毛‘,password=‘limaomao‘,age=23)
      user.save()
      userextra = UserExtra(birthday=date,address=‘杭州市西湖区‘)
      userextra.user = user
      userextra.save()

  一对一之查询:
    已知从表中的一条数据,查询主表中相关联的数据,这时候就好像操作类实例去查询出它的一个属性一样:
      userextra = UserExtra.objects.first()
      print(userextra.user)

    已知主表中的一条数据,查询从表中的相关数据,其实就是使用在OneToOneField创建时在主表中生成的以从表名小写命名的属性或者related_name中传递的值作为属性去查询出从表中相关数据:
      user = User.objects.first()
      userextra = user.extra
      print(userextra)

多对多
  首先,为了方便理解,我们把使用ManyToManyField的字段所在的表称为从表,被连接的表称为主表。

  应用场景:图书和作者之间关系,一本书可以有多个作者,一个作者可以写多本书

  实现方式:在django中实现多对多是使用ManyToManyField,实质上是生成第三张中间表,在中间表中有两个外键分别连接从表和主表:

    class Author(models.Model):
      name = models.CharField(max_length=32)
      age = models.PositiveSmallIntegerField()
      books = models.ManyToManyField(‘Book‘,related_name=‘authors‘)

    class Book(models.Model):
      name = models.CharField(max_length=64,blank=True)
      content = models.TextField(blank=True)
      publisher = models.ForeignKey(Publisher,on_delete=models.SET_NULL,null=True,
      related_name=‘book‘,related_query_name=‘books‘)

  详解:当使用多对多的方式实现连表操作时,主表中将会自动被赋予一个从表名小写+_set的属性,这是一个ManyRelatedManager对象,这个属性名称当然也同样可以被简化成related_name所赋予的值,利用这个属性,我们可以在已知主表中的一条数据的情况下,查询出从表中所有与之关联的数据,同样这个属性同样也支持add函数,但是这个add函数与多对一之中的add函数不同,不能使用bulk参数,所以这里的添加操作都是已经在数据库中存在的数据,如果原先不存在,则必须先使用save函数保存到数据库。其实从表中使用ManyToManyField的字段同样拥有这样的功能,这是一个对称的过程。
  def many_to_many_view(request):
    author = Author(name=‘徐大蒙‘,age=24)
    author.save()
    book = Book.objects.first()
    book.authors.add(author)

    return HttpResponse(‘success‘)

  多对多之查询:
    已知从表中的数据,查询主表中与之关联的所有数据:
      author = Author.objects.first()
      books = author.books.all() # 此时使用的是从表中使用ManyToManyField字段的字段名进行查询,这个字段也是一个ManyRelatedManager对象,也可以使用all(),filter()等函数
      for book in books:
        print(book)

    已知主表中的数据查询从表中所有与之相关的数据:
      book = Book.objects.get(pk=2)
      authors = book.authors.all() # 未定义related_name的情况下使用book.author_set.all()
      for author in authors:
      print(author)

原文地址:https://www.cnblogs.com/limaomao/p/9277920.html

时间: 2024-11-09 19:38:23

django ORM中的表关系的相关文章

django orm中 get 与filter的区别

django orm中 get 与filter的区别: 以前误以为get与filter的区别仅仅是filter返回多条,而get仅支持一条记录,直到使用related_name属性 才发现,两者的差异远不止如此,最本质的区别是 filter返回的值是一个queryset对象, 而get 返回值是一个定义的model对象, 使用get 返回的结果去访问子表对象可以成功,而使用filter就会出错, 是因为queryset 对象没有realtaed_name属性,无法回溯到子表

[Django]orm中的外键级联删除

这里的系统环境为django1.6   os为win7 今天有个需求说的是添加一个地区表,然后用外键和几个非常重要的实体表来做关联(地区表作为其他表的外键),写完地区的删除操作的时候,测试了下代码,功能正常.可是眼睛移动到控制台输出的时候傻了 connexesql ->DELETE FROM `mngm_device` WHERE `mngm_device`.`area_id` IN (%s, %s, %s) connexesql ->DELETE FROM `ad_ad` WHERE `ad

django ORM中的RelatedManager(关联管理器)

关联管理器应用在 一对多的表 或者 多对多的表 多对多表中的用法: 在多对多的表中 正向查询 #基于对象的查询 #正查 # author_obj = Author.objects.get(id=1) # print(author_obj) #<Author object: 1 吴晓波> # print(author_obj.book_set.all()) #出版过的所有的书 <QuerySet [<Book: 小王子>, <Book: 哈利波特>]> 在反向

Django ORM中常用字段和参数

Django ORM 常用字段和参数 常用字段 AutoField int自增列,必须填入参数primary_key=True.当model中如果没有自增列,则自动会创建一个列名为id的列. IntegerField 一个整数类型,范围在 -2147483648 to 2147483647.(一般不用它来存手机号(位数也不够),直接用字符串存,) CharField 字符类型,必须提供max_length参数, max_length表示字符长度. 这里需要知道的是Django中的CharFiel

django ORM中models的字段以及参数

字段: AutoField(Field)         - int自增列,必须填入参数 primary_key=True     BigAutoField(AutoField)         - bigint自增列,必须填入参数 primary_key=True         注:当model中如果没有自增列,则自动会创建一个列名为id的列         from django.db import models         class UserInfo(models.Model):

django ORM中的复选MultiSelectField的使用

在django ORM的使用中,经常会出现选择的情况,例如: class person(odels.Model): sex_type = (('male',u'男'), ('female',u'女')) sex = models.CharField(u"性别", choices=sex_type,max_length=32) 但并不是所有的选择都是只有一个结果的,例如 class person(odels.Model): language_choices= (('chinese',u'

5.Django|模型层--多表关系

多表操作 一对多Book id title price publish email addr 1 php 100 人民出版社 111 北京 2 python 120 沙河出版社 222 沙河 3 go 110 人民出版社 119 北京 4 java 300 人民出版社 111 北京 Book多 id title price publish_id 1 php 100 1 2 python 120 1 3 go 110 2 4 java 300 1 Publish一 id name email ad

Django ORM 一对多表的创建

前面已经学习了在Django里面,如何对单表进行增删改查询.下面学习一下如果存在外键约束的情况下,如何创建. 例1 models.py from django.db import models class UserGroup(models.Model):     uid = models.AutoField(primary_key=True)     caption = models.CharField(max_length=32,unique=True)     ctime = models.

Django ORM中使用update_or_create功能

https://www.cnblogs.com/aguncn/p/4922654.html 今天,看了看官方文档,关于这个update_or_create,有了新的作法. 原理,就是filter条件照写,但使用一个defaults 字典来来决定是新增还是更新. 我自己的写代码片断如下: defaults = dict() defaults['name'] = '{}-{}-yaml'.format(app, env) defaults['content'] = yaml_content AppE