zoukankan      html  css  js  c++  java
  • day055&056Django之多表操作,多表查询

    本节内容:

    1、回顾一对一、一对多、多对多的表结构关系
    2、创建模型
    3、添加表记录
    4、基于对象的跨表查询
    5、基于双下划线的跨表查询
    6、聚合查询与分组查询
    7、F查询与Q查询
    

    一、回顾一对一、一对多、多对多的表结构关系

    1、一对多关系表

    一本书只有一个出版社,一个出版社可以出版多本书
    关联字段在“多”的表中
    
    book
    id  title  publish_id
    1   java       1
    2   go         1
    
    
    publish
    id name  email addr
    1  AAA   123   bejing
    
    SQL

    2、多对多创建关系表

    表之间的关系,书和作者的关系,一本书可以有多个作者,一个作者可以有多本书
    
    多对多创建关系表
         Book表
         id  title  publish_id
          1   java       1
          2   go         1
    
          Author表
          id name
          1  alex
          2  yuan
    
          book2author对应关系表(借助第三张表)
    
          id book_id  author_id
           1   1         1
           2   1         2
           3   2         2
    
    SQL

    3、一对一关系表

    关联字段可以建立在任意表下,但必须唯一约束。
    
    Author
        id name  ad_id(unique约束)
        1  alex    1
        2  yuan    2
    
    AuthorDetail
        id gender   addr       gf    ID      author_id
        1   male   beijing   铁锤   131        1
    
        2   male   beijing   钢弹    151       2
    
    SQL

    二、创建模型

    1、 实例:图书管理

    我们来假定下面这些概念,字段和关系
    
    作者模型:一个作者有姓名和年龄。
    
    作者详细模型:
    把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。
    作者详情模型和作者模型之间是一对一的关系(one-to-one)
    
    出版商模型: 出版商有名称,所在城市以及email。
    
    书籍模型:  书籍有书名和出版日期,
    一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);
    一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)
    
    Bash
    book这个app下的models.py文件代码
    from django.db import models
    
    # Create your models here.
    
    class Book(models.Model):
        title = models.CharField( max_length=32)
        pub_date=models.DateField()
        price=models.DecimalField(max_digits=5,decimal_places=2)
        # 与Publish建立一对多的关系,外键字段建立在多的一方
        publish=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE,null=True) # 字段名默认为,publish_id ,on_delete级联删除,删一个其他的跟着删除
        # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
        authors=models.ManyToManyField("Author",db_table="book2authors") # 创建关系表, db_table关系表的名字可以在这里设定
        def __str__(self):
            return self.title
    
    class Publish(models.Model):
        name=models.CharField( max_length=32)
        city=models.CharField( max_length=32)
        email=models.CharField(max_length=32)
        def __str__(self):
            return self.name
    
    class Author(models.Model):
        name=models.CharField( max_length=32)
        age=models.IntegerField()
        #books=models.ManyToManyField("Book")
        ad=models.OneToOneField("AuthorDetail",null=True,on_delete=models.CASCADE)
        def __str__(self):
            return self.name
    class AuthorDetail(models.Model):
        birthday=models.DateField()
        telephone=models.BigIntegerField()
        addr=models.CharField( max_length=64)
        # author=models.OneToOneField("Author",on_delete=models.CASCADE)
        def __str__(self):
            return str(self.telephone)
    
    Python

    2、写这个表格对象的python代码的—注意事项

    1、表的名称myapp_modelName,是根据 模型中的元数据自动生成的,
    也可以覆写为别的名称,就是重命名
    
    2、id字段默认会自动添加且为主键,可以不写,
    
    3、对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名
      所以我们在写外键字段时,就只写关联的表名
    
    4、这个例子中的CREATE TABLE SQL 语句使用PostgreSQL 语法格式,
      要注意的是Django 会根据settings 中指定的数据库类型来使用相应的SQL 语句。
    
    5、定义好模型之后,你需要告诉Django _使用_这些模型。
    你要做的就是修改配置文件中的INSTALL_APPSZ中设置,在其中添加models.py所在应用的名称
    
    6、外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。
    
    Bash

    二、添加表记录

    添加记录前的准备工作,创建好数据库,
    1、选择MySQL数据库(常用),还是sqlite3数据库,看需求。
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME':'day056orm', # 要连接的数据库,连接前需要创建好
            'USER':'root', # 连接数据库的用户名
            'PASSWORD':'123', # 连接数据库的密码
            'HOST':'127.0.0.1', # 连接主机,默认本级
            'PORT':3306  #  端口 默认3306
        },
    }
    
    注意:使用MySQL数据库时记得在启动文件夹下的__init__文件中,
        添加import pymysql
            pymysql.install_as_MySQLdb()
        然后启动python manage.py makemigrations命令和python manage.py migrate
        就创建好了,我们写好的表结构。
    
    Bash

    1、创建一些基础表(被关联的表)

    创建publish表

    创建author表

    创建authordetail表:

    2、绑定关系

    首先在urls.py中绑定好urls分发,path('add/',views.add),
    在book的app下创建好,def add(request):视图函数
    

    1、绑定一对多的关系

    创建表记录及绑定其对应的关系
    def add(request):
        # 绑定一对多关系
        # 创建书籍和出版社
        # 方式1:
        # book=models.Book.objects.create(title="linux",price=122,pub_date="2012-12-12",publish_id=1)
    
        # 方式2:
        # pub_obj=models.Publish.objects.filter(name="人民出版社").first() # 拿到publish对象
        # book=models.Book.objects.create(title="python",price=223,pub_date="2012-11-11",publish=pub_obj)
        # print(book.publish_id)
        # print(book.publish) # book书籍的出版社对象
    
        # 查询python书籍的出版社的邮箱
        # 方式1,双下划线查询
        # email=models.Book.objects.filter(title="python").values("publish__email")
        # print(email)
    
        # email=models.Publish.objects.filter(id=book.publish_id).first().email  # book是上面的表记录对象
        # print(email)
    
        # print(book.publish.email)
        return HttpResponse("创建成功")
    
    核心:
        book.publish和book.publish_id具体是什么?
        1、book.publish  # 直接拿到的是出版社对象,
        2、book.publish_id  # 拿到是出版社对象对应的id
    
    Python

    2、绑定多对多关系

    绑定多对多的关系, 无非就是在关系表中创建记录
    
    绑定多对多关系
    # linux这本书绑定两个作者: alex,egon
    
    # linux=models.Book.objects.filter(title="linux").first()
    # alex=models.Author.objects.filter(name="alex").first()
    # egon=models.Author.objects.filter(name="egon").first()
    # linux.authors.add(alex,egon) # Book对象直接点外键字段,就可以找到第三张关系表
    #
    # linux.authors.add(1)  # 为这个Book对象添加一个作者,
    # linux.authors.add(*[1,2])  # 打散列表,为该书籍添加列内的所有作者
    #
    # linux.authors.remove(alex,) # 为该书籍删除一个作者
    # linux.authors.clear() # 清空该Book对象的关系表的关联关系
    #
    # linux.authors.set([1,])  # set先清空之前所有的记录(作者),重新写入,类似于文件写入前清空
    
    # 绑定多对多关系,重点是在关系表上创建记录,做好两个表之间的对应关系
    
    
    ######### 正向操作按字段,反向操作按表名小写
    
    linux = models.Book.objects.filter(title='linux').first()
    go = models.Book.objects.filter(title="go").first()
    alex = models.Author.objects.filter(name="alex").first()
    # 给alex作者绑定两本书籍: linux,go
    alex.book_set.add(linux,go)  # 单个的时候直接操作,多个对象是使用_set操作
    
    核心:book_obj.authors.all()是什么?
      待续
    
    Python

    四、基于对象的跨表查询

    一 基于对象的跨表查询( 子查询:以上一次的查询结果作为下一次的查询条件)
       (1)一对多
                         正向查询:按字段 book.publish
         Book对象(多)---------------------------------- >  Publish 对象
                      <---------------------------------
                        反向查询:按表名小写_set.all()
    
    
        (2)多对多
                       正向查询:按字段 book.authors.all()
         Book对象    ---------------------------------- >  Author 对象
                      <---------------------------------
                        反向查询:按表名小写_set.all()
    
    
        (2)一对一
                        正向查询:按字段 book.ad
         Author 对象   ---------------------------------- >  AuthorDetail 对象
                      <---------------------------------
                        反向查询:按表名小写
    
    Bash
    基于对象的跨表查询
    def query(request):
        #(1)一对多
    
        # 1 查询linux这本书的出版社的城市(正向查询)
        # book=models.Book.objects.filter(title='linux').first()
        # print(book.publish.city) # Book对象直接点外键字段就是出版社对象,直接点城市就行了
    
        # 2 查询人民出版社出版的所有书籍(反向查询)
        # publish=models.Publish.objects.filter(name='人民出版社').first()
        # queryset=publish.book_set.all() # 这是拿到的是一个集合
        # print(queryset)  # <QuerySet [<Book: linux>, <Book: python>]>
    
    
        # 2、多对多
    
        # 1 查询linux书籍的所有作者(正向查询)
        # linux=models.Book.objects.filter(title="linux")
        # queryset=linux.authors.all()  # 这样就可以拿到所有的书籍对象集合,因为设置了__str__
        # print(queryset)
    
        # 2 查询alex作者出版过的所有书籍
        # alex=models.Author.objects.filter(name='alex').first() # 记得从集合中取出第一个对象
        # queryset=alex.book_set.all() # 反向查询表名_set
        # print(queryset)  # <QuerySet [<Book: linux>]>
    
    
        # 3 一对一
        # 1 查询alex的手机号
        # alex=models.Author.objects.filter(name="alex").first()
        # print(alex.ad.telephone)
    
        # 2 查询手机号为110的作者的名字
        # tel=models.AuthorDetail.objects.filter(telephone=911).first()
        # print(tel.author.name) # 不是集合对象,直接表名(小写).出来
        return HttpResponse("查询成功")
    
    Python

    五、基于双下划线的跨表查询

    KEY:通知ORM引擎如何跨表: 正向查询按字段,反向查询按表名小写
    
    基于双下划线的跨表查询
    def query(request):
        # 1、查询linux这本书的出版社地址
        # 方式1  正向查询
        # queryset=models.Book.objects.filter(title="linux").values("publish__city")
        # print(queryset) # filter得到的queryset集合对象
    
        # 方式2 反向查询
        # queryset=models.Publish.objects.filter(book__title="linux").values("city")
        # print(queryset)
    
        # 2 查询linux书籍的所有作者
        # queryset=models.Book.objects.filter(title="linux").values("authors__name")
        # queryset=models.Book.objects.filter(title__startswith="li").values("authors__name")  # 重点
        # print(queryset)
    
        # queryset=models.Author.objects.filter(book__title="linux").values("name") # 反向查询
    
        # 3 查询alex的手机号
        # queryset=models.Author.objects.filter(name="alex").values("ad__telephone") # 正向
        # queryset=models.AuthorDetail.objects.filter(author__name="alex").values("telephone") # 反向
        # print(queryset)
    
    
        # 连续跨表
        # 4 查询人民出版社出版过的所有书籍的名字及作者的姓名
        queryset=models.Book.objects.filter(publish__name="人民出版社").values("title","authors__name") # 正向查询
    
        # queryset=models.Author.objects.filter(book__publish__name="人民出版社").values("book__title","name") # 反向查询
        # 默认都是left join,所以如果有存在的左边基准的值为空,那么就会不保留这条记录
        print(queryset)
    
    
        return HttpResponse("查询成功")
  • 相关阅读:
    PHP filter_var() 函数
    jquery 表格(点击列标题,保留当前列,其他列隐藏)
    jquery 表格(表格记录分页显示)
    jquery 表格(点击行或列,隐藏当前选中的行或列)
    jquery 表格(鼠标悬停改变改变行背景+隔行换色)
    jquery 表格(鼠标悬停列标题,改变该列的背景色)
    你不了解的PHP 的10件事情(转)
    优化PHP代码的40条建议(转)
    jquery 表格(展开和折叠列表项)
    IDENT_CURRENT
  • 原文地址:https://www.cnblogs.com/yipianshuying/p/10223411.html
Copyright © 2011-2022 走看看