永远爱学习

导航

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相关的知识点,或许还得看一下源码。请知道的大佬告诉我一声.

posted on 2019-01-16 11:51  永远爱学习  阅读(307)  评论(0)    收藏  举报