Django many-to-many relationships, django many-to-Relationship
Django 1, 1.7
Use ManyToManyFiled to define multiple-to-multiple relationships.
In this example, the Article can be published on multiple publications, and the Publication can have multiple Article objects.
from django.db import modelsclass 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',)
The following is an example of using Python APIs. Note: If you use an intermediate model for many-to-many relationships, some relational manager methods cannot be used, so some of these examples cannot work under this model.
Create several publications:
>>> P1 = Publication (title = 'the Python Journal ')
>>> P1.save ()
>>> P2 = Publication (title = 'science News ')
>>> P2.save ()
>>> P3 = Publication (title = 'science wekkly ')
Create an article:
>>> A1 = Article (headline = 'django lets you build web apps easily ')
Before saving it, it cannot be associated with a Publication.
>>> A1.publications. add (p1)
...
ValueError: 'Article' instance needs to have a primary key value before a failed-to-assign relationship can be used.
Save
>>> A1.save ()
Associate Article with Publication:
>>> A1.publications. add (p1)
Create another Article and set it to appear in two Publications:
>>> A2 = Article (headline = 'nasa uses python ')
>>> A2.save ()
>>> A2.publications. add (p1, p2)
>>> A2.publications. add (p3)
The 2nd add operation is correct:
>>> A2.publications. add (p3)
Adding an error type object produces a TypeError:
>>> A2.publictaions. add (a1)
Traceback (most recent call last ):
...
TypeError: 'publication' instance already ted
Use create () to create a Publications and add it to an article:
>>> New_publication = a2.publications. create (title = 'highlights for Children ')
Article objects can access their associated Publication objects:
>>> A1.publications. all ()
[<Publication: HIghlights for Children>,...]
>>> A2.publications. all ()
[<Publication: Highlights for Children>, <Publication: Science News>,...]
Publication objects can access their associated Article objects:
>>> 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>]
You can use cross-link query to obtain multi-to-Multi-link queries:
>>> 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>]
The count () function also uses 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>]
Reverse m2m query is also supported (for example, starting from a table without the ManyToManyField field ):
>>> 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>,...]
Excluding an associated project will work as expected (although the SQL used is a little complicated ):
>>> Article. objects. exclude (publications = p2)
[<Article: Django lets you build Web apps easily>]
If we delete Publication, its Article will not be able to access it:
>>> P1.delete ()
>>> Publication. objects. all ()
[<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly> ']
>>> A1 = Article. objects. get (pk = 1)
>>> A1.publications. all ()
[]
If we delete an Article, its Publications will not be able to access it:
>>> A2.delete ()
>>> Article. objects. all ()
[<Artilce: Django lets you bulid Web apps easily>]
>>> P2.article _ set. all ()
[]
Add through the other end of m2m:
>>> A4 = Article (headline = 'nasa finds intelligent lif on global ')
>>> A4.save ()
>>> P2.article _ set. add (a4)
>>> P2.article _ set. all ()
[<Article: NASA finds intelligent lif on Earth>]
>>> A4.publications. all ()
[<Publication: Science News>]
Add using keywords on the other end:
>>> 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>]
Remove Publication from 1 Article:
>>> A4.publications. remove (p2)
>>> P2.article _ set. all ()
[<Article: Oxygen-free diet works wonders>]
>>> A4.publications. all ()
[]
From the other end:
>>> P2.article _ set. remove (a5)
>>> P2.article _ set. all ()
[]
>>> A5.publications. all ()
[]
You can assign values to a relational set. The assign value operation clears any existing set members:
>>> A4.publications. all ()
[<Publication: Science News>]
>>> A4.publications = [p3]
>>> A4.publications. all ()
[<Publication: Science Weekly>]
Link set can be cleared:
>>> P2.article _ set. clear ()
>>> P2.article _ set. all ()
[]
You can also clear from the other end:
>>> 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>]
Re-create the articles and Publications we have deleted:
>>> P1 = Publication (title = 'the Python Journal ')
>>> P1.save ()
>>> A2 = Article (headline = 'nasa uses python ')
>>> A2.save ()
>>> A2.publications. add (p1, p2, p3)
Batch delete some Publications-reference deleted publications are also deleted:
>>> 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>]
Batch delete some articles-objects referenced and deleted are also deleted:
>>> Q = Article. objects. filter (headline _ startwith = 'django ')
>>> Print (q)
[<Article: Django lets you build Web apps easily>]
>>> Q. delete ()
After delete () is called, The QeruySet cache needs to be cleared, and the music object will also be deleted:
>>> Print (q)
[]
>>> P1.article _ set. all ()
[<Article: NASA uses Python>]
The alternative to calling clear () is to assign a null set:
>>> 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 ()
[]