Django中ForeignKey和ManyToMany使用探究
实验所用的models:
class Publication(models.Model):
name = models.CharField(max_length=64)
def to_dict(self):
return {'id': self.id, 'name': self.name}
def __str__(self):
return f'{self.name}'
class Person(models.Model):
name = models.CharField(max_length=64)
age = models.IntegerField()
def to_dict(self):
return {'id': self.id, 'name': self.name}
def __str__(self):
return f'{self.name}'
class Book(models.Model):
name = models.CharField(max_length=64)
author = models.ForeignKey(
Person,
null=True,
on_delete=models.CASCADE,
related_name='author_book',
)
# 暂时认为一本书对应的是一个出版商
publication = models.ForeignKey(
Publication,
null=True,
on_delete=models.CASCADE,
)
def to_dict(self):
return {'id': self.id, 'name': self.name}
def __str__(self):
return f'{self.name}'
class BookShop(models.Model):
name = models.CharField(max_length=64)
book = models.ManyToManyField(
Book,
related_name='book_bookshop',
)
person = models.ManyToManyField(
Person,
related_name='author_in_bookshop',
)
publication = models.ManyToManyField(
Publication,
)
def to_dict(self):
return {'id': self.id, 'name': self.name}
def __str__(self):
return f'{self.name}'
1.ForeignKey
在1:m的关系中会用到,都是一那一方作为外键。
比如 book:person 就是 m:1的关系
django中 要在book class中进行定义: author=models.ForeignKey(Person,related_name='book')
那么在mysql中生成数据表的时候就会看见:
Book表中会有author_id一列
使用:
books = Book.objects.all()
books.first().author
# 仔细想一下,这样查出来的author,应该是一个对象,因为是外键,这是一对多的关系
# 这里很明显是每一本书都对应一个author,所以不要用什么book.first().author.all()这样的东西,不对的。
另外我们再思考一下:
persons = Person.objects.all()
persons.first().author_book.all() 就可以双向查询了
2.ManyToMany
在n:m的关系中会用到,是双方互为对方的外键。
比如 book:bookshop 就是n:m的关系
这个在哪一方中定义 其实都是可以的
但是如果Book定义在BookShop之前,就应该在Bookshop之前进行定义
否则就会出现错误。
class BookShop(models.Model):
book = models.ManyToManyField(
Book,
related_name='book_bookshop',
)
这样在mysql中会生成数据表:
book_bookshop表,表中会有id, bookshop_id,book_id三列
使用:
bookshops = BookShop.objects.all()
bookshops.first().person.all()
这个不用说了,由于多对多的关系,所以bookshop对应的肯定是多个person
同理啊
bookshops.first().book.all() 可以查询到第一家书店里面的所有书籍
我们也要思考一下这个问题:
persons = Person.objects.all()
persons.first().person_in_bookshop.all() 应该这样查
第一种定义多对多结构的方式:
class BookShop(models.Model):
person = models.ManyToManyField(
Person,
related_name='author_in_bookshop',
)
person.first().bookshop_set.all() (x) 不可以这样使用的
应该这样用:persons.first().person_in_bookshop.all() 应该这样查
第二种定义多对多结构的方式:
class BookShop(models.Model):
publication = models.ManyToManyField(
Publication,
)
publication = Publication.objects.first()
publication.bookshop_set.all() 就可以找到这家出版社 出版过的书所在的所有的书店了
但是为什么定义了related_name以后就不能使用modelname_set的原因我就不知道了
也许应该查一下manager相关的知识点,或许还得看一下源码。请知道的大佬告诉我一声.
浙公网安备 33010602011771号