django之多对多关系

django 1.7

定义多对多关系,使用 ManyToManyFiled。

本例中,文章Article可以在多个出版物Publication上发表,而出版物可以有多个文章对象。

from django.db import models

class Publication(models.Model):
    title = models.CharField(max_length=30)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ('title',)

class Article(models.Model):
    headline = models.CharField(max_length=100)
    publications = models.ManyToManyField(Publication)

    def __str__(self):
        return self.headline

    class Meta:
        ordering = ('headline',)

下面是使用Python API执行例子的操作。注意,若你为多对多关系使用了中间体模型,有些关系管理器的方法不能使用,因此这些例子中某些在这种模型下不能工作。

创建几个出版物:

>>> p1 = Publication(title=‘The Python Journal‘)

>>> p1.save()

>>> p2 = Publication(title=‘Science News‘)

>>> p2.save()

>>> p3 = Publication(title=‘Science wekkly‘)

创建文章:

>>> a1 = Article(headline=‘Django lets you build web apps easily‘)

在保存它以前,不能与一个Publication关联。

>>> a1.publications.add(p1)

...

ValueError:  ‘Article‘ instance needs to have a primary key value before a many-to-many relationship can be used.

保存

>>> a1.save()

把Article关联到Publication:

>>> a1.publications.add(p1)

创建另一个Article,设定它在两个Publications中出现:

>>> a2 = Article(headline=‘NASA uses Python‘)

>>> a2.save()

>>> a2.publications.add(p1, p2)

>>> a2.publications.add(p3)

第2次添加也是正确的:

>>> a2.publications.add(p3)

添加一个错误类型的对象会产生一个 TypeError:

>>> a2.publictaions.add(a1)

Traceback (most recent call last):

...

TypeError: ‘Publication‘ instance excepted

使用create()一步创建Publications并把它添加到一个文章中:

>>> new_publication = a2.publications.create(title=‘Highlights for Children‘)

Article对象可以访问它们关联的Publication对象:

>>> a1.publications.all()

[<Publication: HIghlights for Children>, ...]

>>> a2.publications.all()

[<Publication: Highlights for Children>, <Publication: Science News>, ... ]

Publication 对象可以访问它们关联的Article对象:

>>> p2.article_set.all()

[<Article: NASA uses Python>]

>>> p1.article_set.all()

[<Article: Django lets you build Web app easyily>, <Article: NASA uses Python>]

>>> Publication.objects.get(id=4).article_set.all()

[<Article: NASA uses Python>]

可以使用跨关系查询来获得多对多关系查询:

>>> Article.objects.filter(publications__id=1)

[<Article: Django lets you build Web app easyily>, <Article: NASA uses Python>]

>>> Article.objects.filter(publications__pk=1)

[<Article: Django lets you build Web app easyily>, <Article: NASA uses Python>]

>>> Article.objects.filter(publications=1):

[<Article: Django lets you build Web app easyily>, <Article: NASA uses Python>]

>>> Article.objects.filter(publications=p1)

[<Article: Django lets you build Web app easyily>, <Article: NASA uses Python>]

>>> Article.objects.filter(publications__title__startwith=‘Science‘)

[<Article: NASA uses Python>, <Article: NASA uses Python>]

>>> Article.objects.filter(publications__title__startwith=‘Science‘).distinct()

[<Article: NASA uses Python>]

count()函数也使用distinct():

>>> Article.objects.filter(publications__title__startwith=‘Science‘).count()

2

>>> Article.objects.filter(publications__title__startwith=‘Science‘).distinct().count()

1

>>> Article.objects.filter(publications__in=[1,2]).distinct()

[<Article: Django lets you build Web app easyily>, <Article: NASA uses Python>]

>>> Article.objects.filter(publications__in=[p1,p2]).distinct()

[<Article: Django lets you build Web app easyily>, <Article: NASA uses Python>]

反向m2m查询也被支持(如,从不含ManyToManyField字段的表开始):

>>> Publication.objects.filter(id=1)

[<Publication: The Python Journal>]

>>> Publication.objects.filter(pk=1)

[<Publication: The Python Journal>]

>>> Publication.objects.filter(article__headline__startwith=‘NASA‘)

[<Publication: Highlights for Children>, <Publication: Science News>, ... ]

>>> Publication.objects.filter(article__id=1)

[<Publication: The Python Journal>]

>>> Publication.objects.filter(article__pk=1)

[<Publication: The Python Journal>]

>>> Publication.objects.filter(article=1)

[<Publication: The Python Journal>]

>>> Publication.objects.filter(article=a1)

[<Publication: The Python Journal>]

Publication.objects.filter(article__in=[1,2]).distinct()

[<Publication: Highlights for Children>, <Publication: Science News>, ... ]

>>> Publication.objects.filter(article__in=[a1,a2]).distinct()

[<Publication: Highlights for Children>, <Publication: Science News>, ... ]

排除一个关联项目会按预期工作(尽管使用的SQL有一点复杂):

>>> Article.objects.exclude(publications=p2)

[<Article: Django lets you build Web apps easily>]

如果我们删除Publication,它的Article将不能访问它:

>>> p1.delete()

>>> Publication.objects.all()

[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>‘]

>>> a1 = Article.objects.get(pk=1)

>>> a1.publications.all()

[ ]

如果我们删除一个Article,它的Publications将不能访问它:

>>> a2.delete()

>>>Article.objects.all()

[<Artilce: Django lets you bulid Web apps easily>]

>>> p2.article_set.all()

[ ]

通过m2m的另一端进行添加:

>>> a4 = Article(headline=‘NASA finds intelligent lif on Earth‘)

>>>a4.save()

>>>p2.article_set.add(a4)

>>> p2.article_set.all()

[<Article: NASA finds intelligent lif on Earth>]

>>> a4.publications.all()

[<Publication: Science News>]

通过另一端使用关键字添加:

>>> new_article =  p2.article_set.create(headline=‘Oxygen-free diet works wonders‘)

>>> p2.article_set.all()

[<Article: NASA finds intelligent lif on Earth>, <Article: Oxygen-free diet works wonders> ]

>>> a5 = p2.article_set.all()[1]

>>> a5.publications.all()

[<Publication: Science News> ]

从1个Article移除Publication:

>>> a4.publications.remove(p2)

>>> p2.article_set.all()

[<Article: Oxygen-free diet works wonders>]

>>> a4.publications.all()

[ ]

而从另一端:

>>> p2.article_set.remove(a5)

>>>p2.article_set.all()

[ ]

>>> a5.publications.all()

[ ]

可以赋值关系集。赋值操作清除任何存在的集合成员:

>>> a4.publications.all()

[<Publication: Science News>]

>>> a4.publications = [p3]

>>> a4.publications.all()

[<Publication: Science Weekly>]

关系集可以清除:

>>> p2.article_set.clear()

>>> p2.article_set.all()

[ ]

也可以从另一端做清除:

>>> p2.article_set.add(a4, a5)

>>> p2.article_set.all()

[<Article: NASA finds intelligent lif on Earth>, <Article: Oxygen-free diet works wonders> ]

>>> a4.publications.clear()

>>> a4.publications.all()

[ ]

>>> p2.article_set.all()

[<Article: Oxygen-free diet works wonders> ]

重新创建我们删除的Article和Publications:

>>> p1 = Publication(title=‘The Python Journal‘)

>>> p1.save()

>>> a2 = Article(headline=‘NASA uses Python‘)

>>> a2.save()

>>> a2.publications.add(p1, p2, p3)

批量删除一些Publications - 引用删除的publications也被删除:

>>> Publication.objects.filter(title__startwith=‘Science‘).delete()

>>> Publication.objects.all()

[<Publication: Highlights for Children>, <Publication: The Python Journal>]

>>> Article.objects.all()

[<Article: Django lets you build Web apps easily>, .... ]

>>> a2.publications.all()

[<Publication: The Python Journal>]

批量删除一些article - 引用删除的对象也被删除:

>>> q = Article.objects.filter(headline__startwith=‘Django‘)

>>> print(q)

[<Article: Django lets you build Web apps easily>]

>>> q.delete()

在delete()调用后,QeruySet缓存需要清除,而且音乐的对象也会删掉:

>>> print(q)

[ ]

>>> p1.article_set.all()

[<Article: NASA uses Python>]

调用clear()的替代方法是赋值空集:

>>> p1.article_set = []

>>> p1.article_set.all()

>>> a2.publications = [p1, new_publication]

>>> a2.publications.all()

[<Publication: Highlights for Children>, <Publication: The Python Journal>]

>>> a2.publications = [ ]

>>> a2.publications.all()

[ ]

时间: 2024-12-28 09:21:53

django之多对多关系的相关文章

django ManyToManyField多对多关系

Django 的 ORM 有多种关系:一对一,多对一,多对多 各自定义的方式为 : 一对一: OneToOneField 多对一: ForeignKey 多对多: ManyToManyField 上边的描述太过数据而缺乏人性化,我们来更人性化一些: 多个属于一个,即 belong to :  ForeignKey,多个属于一个 一个有一个,即 has one: OneToOneField 一个有很多个,即 has many:  lots of A belong to B 与 B has many

Django 一对多,多对多关系解析

[转]Django 一对多,多对多关系解析 Django 的 ORM 有多种关系:一对一,多对一,多对多. 各自定义的方式为 : 一对一: OneToOneField 多对一: ForeignKey 多对多: ManyToManyField 上边的描述太过数据而缺乏人性化,我们来更人性化一些: 多个属于一个,即 belong to :  ForeignKey,多个属于一个 一个有一个,即 has one: OneToOneField 一个有很多个,即 has many:  lots of A b

Django 多对多关系的增删改查

目录 Django多对多数据增删改查 1.表结构及基本方法 2.查 3.增 4.改 Django多对多数据增删改查 1.表结构及基本方法 1.表结构 # models.py class Book(models.Model): author = models.ManyToMany(to='author', relate_name='author') """ ...字段 """ class author(models.Model): "&q

Django多对多关系建立及Form组件

目录 Django多对多关系 1.创建方式一全自动 2.创建方式二纯手撸 3.半自动(推荐使用) forms校验组件 使用forms组件实现注册功能 form常用字段和插件 数据校验 钩子函数 HOOK Django多对多关系 1.创建方式一全自动 class Book(models.Model): title = models.CharField(max_length=32) # 多对多关系字段 authors = models.ManyToManyField(to='Authors') cl

&lt;三&gt;django模板 模型 模型关系

django模板 模板查找顺序: 查找顺序 setting.py(INSTALL_APPS)顺序查找(APP)templates目录下的所有模板名字的字符串匹配(先全局,再局部),一旦匹配就不会再找 查找路径 完整路径:$APP/templates/user/login.html(从templates路径下算起) from django.shortcuts import render from django.views import View from django.views.generic.

jango 模型管理数据model,数据库外键主键与一对一,一对多,多对多关系

四.models.py 定义和管理模型: 4.1模型class的属性就映射与数据库的字段参数 继承models.Model class TestClass(models.Model): 4.2在数据库生成数据表: #django默认在makemigrations会为表对象创建主键id,id = models.AutoField(primary_key=True) 你也可以自定义一个主键对象: 4.2.1: 生成迁移文件python manage.py makemigrations 4.2.2执行

第六章、创建多对多关系的三种方式

目录 第六章.创建多对多关系的三种方式 一.创建多对多关系的三种方式 1. 全自动(推荐指度**) 2. 纯手动(不推荐) 3. 半自动(******) 第六章.创建多对多关系的三种方式 一.创建多对多关系的三种方式 1. 全自动(推荐指度**) 全自动:利用 ManyToManyField 让 django 自动创建第三张表 优点:不需要手动创建第三张表 不足:由于第三张表不是你手动创建的,也就意味着第三张表中字段是固定的,无法做扩展 class Book(models.Model): ...

Django:表多对多查询、聚合分组、FQ查询、事务

1表多对多的关系查询 准备工作创建表结构 from django.db import models # Create your models here. class Publisher(models.Model): name = models.CharField(max_length=32, verbose_name="名称") def __str__(self): return self.name class Book(models.Model): title = models.Ch

Laravel5.1 模型 --多对多关系

多对多关系也是很常用的一种关系,比如一篇文章可以有多个标签,一个标签下也可以有多篇文章,这就是一个典型的多对多的关系. 1 实现多对多关系 多对多关系我们需要三张表,一张是文章另一张是标签,第三章表是它们的中间表 因为多对多关系需要抽离成两个一对多关系嘛. 1.1 文章结构 public function up() { Schema::create('articles', function (Blueprint $table) { $table->increments('id'); $table