• 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()

  • 相关阅读:
    nginx 安装教程
    php 安装教程
    第一个AWK程序的尝试
    memcached-tool 工具
    java数据库 DBHelper
    Innodb的三大关健特性
    我遇到的一个ClassNotFoundException问题
    storm学习初步
    再探 jQuery
    简单聊一聊正则表达式中的贪婪匹配和非贪婪匹配
  • 原文地址:https://www.cnblogs.com/yinsedeyinse/p/12452656.html
Copyright © 2020-2023  润新知