Django学习笔记〇五——DJango中ORM的外键的使用

我们在前面讲了Django中ORM的大致使用方法,我们今天要了解一些常用的外键的使用方法。

常用外键ForeignKey

一对多的模型

我们在建立模型的时候可以直接在类中对外键直接定义好。结合在下一章要用的案例,我们做这样一个一对多的数据库模型

 因为一个出版社可以对应很多本书籍,这就是最常见的一个一对多的外键模型。

用代码反应出来这两个类,就是这样的:

class Publisher(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(null = False,max_length=16)

class Books(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(null=False,max_length=32)
    publisher = models.ForeignKey(to='Publisher',on_delete=models.CASCADE)

注意books里的字段——我们在创建的时候是定义的publisher,但是通过makemigrations和migrate创建的表的对应字段看看MySQL里的字段

 

 

 那个publusher自动加了个_id,我们还可以下面的代码查一下app_books这个表的创建代码来了解一下table的结构。

show create table app_books;
 CREATE TABLE `app_books` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(32) NOT NULL,
  `publisher_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `app_book_publisher_id_74fff6a5_fk_app_publisher_id` (`publisher_id`),
  CONSTRAINT `app_book_publisher_id_74fff6a5_fk_app_publisher_id` FOREIGN KEY (`publisher_id`) REFERENCES `app_publisher` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

查询

下面几种方法写明了通过外键获取指定字段的一步步的过程(分步说明,当然可以直接用最后一个方法),比方我们要知道某本书籍对应的出版社,就可以这么做:

#获取book对象
book = models.Books.objects.get(id=3)
#获取book对象内指定的字段publisher_id(外键)
publisher_id = book.publisher_id
# 获取book对象对应的publisher对象
publisher_obj = book.publisher
#获取book对象获取通过外键映射到另外表的指定字段
publisher = book.publisher.name

反向查询

但是如果我们想了解某个出版社出版了那些书,SQL的语句是这样的:

select * from app_books left join app_publisher on app_books.publisher_id=app_publisher.id where app_publisher.name='机械工业出版社';

又该怎么做呢?下面只放下核心代码

publisher = models.Publisher.objects.get(name = '机械工业出版社')
books = publisher.books_set.all()   
print(type(books))    
for book in books:
    print(book.title)

这样就可以打印出指定的出版社出版了哪些书。知道这里,我才发现了Django的牛X之处。

多对多外键ManyToManyField

 下面我们再看看多对多的外键是怎么使用的。补充一下数据库模型

 

 

 在上面的表中补充一个作者表,书籍和作者的对应关系,有可能一个书是几个作者同时写的,也有可能一个作者写了好几本书。为了把书籍和作者关联起来,就要建立第三个表——book_to_author

看看两个类是怎么构建的

class Books(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(null=False,max_length=32)
    publisher = models.ForeignKey(to='Publisher',on_delete=models.CASCADE)       #这里在创建的时候ORM会直接把外键的名字设置为publisher_id


class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(null=False,max_length=10,unique=True)
    book = models.ManyToManyField(to='Books')           #用了多对多的关联

可以发现,Books的代码跟前面的是一样的,但是在author里定义了一个多对多的外键——ManytoManyField

通过manage.py文件刷新一下数据库,可以发现多出来了一个table

 看看author表和author_books表的构造方法

mysql> show create table app_author;
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table      | Create Table                                                                                                                                                                                      |
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| app_author | CREATE TABLE `app_author` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 |
+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> show create table app_author_book;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table           | Create Table                                                                                                                                                                                  |
+-----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| app_author_book | CREATE TABLE `app_author_book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `author_id` int(11) NOT NULL,
  `books_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `app_author_book_author_id_books_id_226f32e6_uniq` (`author_id`,`books_id`),
  KEY `app_author_book_books_id_92880518_fk_app_books_id` (`books_id`),
  CONSTRAINT `app_author_book_author_id_ac226197_fk_app_author_id` FOREIGN KEY (`author_id`) REFERENCES `app_author` (`id`),
  CONSTRAINT `app_author_book_books_id_92880518_fk_app_books_id` FOREIGN KEY (`books_id`) REFERENCES `app_books` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 |
+-----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

仔细看一下,还有一个表:app_author_book,这个表其实不是我们通过类直接创建的,而是通过ManytoManyField的方式直接创建的。

正向查询

因为我们是通过author表里的属性关联到book的,那么从author获取到book就是正向查询,比方我们需要查询张三都出了什么书

author = models.Author.objects.get(name = '张三')
author_book = author.book.all()
for book in author_book:
    print(book.title)

要注意的是我们通过all()获取的是一个用book对象构成的可迭代的对象,所以用for循环可以取出每一个book对象,然后直接调用属性可以获取值。

反向查询

和前面说的一对多的外键一样,因为在book里我们并没有定义过author这个字段,所以是不能直接找author的,那么如果我们想获取某一本书的作者都有谁,就要用到反向查询

book = models.Books.objects.get(title = '学习Linux')
authors = book.author_set.all()
for author in authors:
    print(author.name)

所以,一定要注意到那个最牛X的用法_set()

 

posted @ 2020-03-10 23:52  银色的音色  阅读(490)  评论(0编辑  收藏  举报