基于对象的跨表查询


跨表查询比较难!要细心的学

1.基于对象的跨表查询

ORM_MULTI/urls.py

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path("query/",views.query)
]

app01/models.py

from django.db import models

# 作者详情表
class AuthorDetail(models.Model):
    nid = models.AutoField(primary_key=True)
    birthday = models.DateField()
    telephone = models.BigIntegerField()
    addr = models.CharField(max_length=64)


# 作者表
class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    authordetail = models.OneToOneField(to='AuthorDetail',to_field='nid',on_delete=models.CASCADE)

    def __str__(self):
        return self.name

# 出版社表
class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()

# book表
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    publishDate = models.DateField()
    price = models.DecimalField(max_digits=5, decimal_places=2)

    create table book_quthor{
	id int primary key quto_increment,
        book_id int,
        author_id int,
        foreign key (book_id) references book(id),
        foreign key (author_id) reference author(id)
    };
    """

    def __str__(self):
        return self.title

app01/views.py

from django.shortcuts import render,HttpResponse
from app01.models import *

def query(request):
    """跨表查询
        1 基于对象查询
        2 基于双下划线查询
        3 聚合和分组查询
        4 F 与 Q 查询
    """
    # ===============  表中数据的准备 =========================
    """
    # AuthorDetail表
    ad_1 = AuthorDetail.objects.create(birthday='2018-01-11',telephone=1234567890,addr="北京沙河")
    ad_2 = AuthorDetail.objects.create(birthday='2017-02-22',telephone=1234567890,addr="上海明珠")
    ad_3 = AuthorDetail.objects.create(birthday='2016-03-30',telephone=1234567890,addr="北京朝阳")
    ad_4 = AuthorDetail.objects.create(birthday='2015-04-02',telephone=1234567890,addr="广州")

    # Author 表
    author_1 = Author.objects.create(name='alex',age=23,authordetail=ad_1)
    author_2 = Author.objects.create(name='egon',age=24,authordetail=ad_2)
    author_3 = Author.objects.create(name='peiqi',age=25,authordetail=ad_3)
    author_4 = Author.objects.create(name='yuan',age=26,authordetail=ad_4)

    # Publish 表
    publish_1 = Publish.objects.create(name="成都中医药大学出版社",city='四川',email="123@成都中医药大学.com")
    publish_2 = Publish.objects.create(name="电子科技大学出版社",city='四川',email="123@电子科技大学.com")

    # Book 表
    book_1 = Book.objects.create(title="Python",publishDate='2018-07-20',price=12.34,publish=publish_1)
    book_2 = Book.objects.create(title="JavaScript",publishDate='2018-07-20',price=12.34,publish=publish_2)
    book_3 = Book.objects.create(title="Vue",publishDate='2018-07-20',price=12.34,publish=publish_2)
    book_4 = Book.objects.create(title="Java",publishDate='2018-07-20',price=12.34,publish=publish_1)

    # 绑定多表关系

    bo_1 = Book.objects.filter(nid="1").first()
    bo_2 = Book.objects.filter(nid="3").first()
    bo_3 = Book.objects.filter(nid="4").first()

    bo_1.authors.add(13,14)
    bo_2.authors.add(15)
    bo_3.authors.add(15)

    """

    # ===============  基于对象的跨表查询 (子查询,)===============
    #       先查询到关联或者被关联的对象,然后根据关联对象进行查询!

    # =====
    # 一对多的正向查询 按字段 查询Vue这本书的出版社的名字 多对一
    book_pub_name = Book.objects.filter(title="Vue").first().publish.name
    """原生的SQL语句
    select
        name
    from
        app01_publish
    where
        nid = (select publish_id from app01_book where title="Vue");
    """

    # 一对多的反向查询 按照表名 表名小写_set 查询电子科技大学出版社出版过的书籍
    publish = Publish.objects.filter(name="电子科技大学出版社").first()
    ret = publish.book_set.filter(title="JavaScript").first()
    print(ret.title)
    """原生SQL
    select title from app01_book where publish_id =
    (select nid from app01_publish where name="电子科技大学出版社");
    """


    # =====
    # 多对多的正向查询 查询Python书籍的所有作者的名字
    book_obj = Book.objects.filter(title="Python").first()
    author_list = book_obj.authors.all()
    print(author_list)

    # 多对多的反向查询 查询peiqi写过的所有的书籍
    author = Author.objects.get(name="peiqi")
    book_list = author.book_set.all()
    print(book_list)

    # =====
    # 一对一的正向查询 查询egon的地址
    egon = Author.objects.filter(name="egon").first()
    addr = egon.authordetail.addr
    print(addr)

    # 一对一的反向查询 查询地址为北京沙河的 Author表名字
    addr = AuthorDetail.objects.filter(addr="北京沙河").first()
    name = addr.author.name
    print(name)

    return HttpResponse("OK")


"""


A-B 假如关联属性在A表中
    正向查询:通过A查询B,正向查询按 字段
    反向查询:通过B查询A  反向查询按 表名_set 一般使用 表名_set.all() 方法
            因为反向查找大内容可能很多个,这里用_set告诉你这个查询的是个集合形式的!

一对多查询
                          book_obj.publish
    Book(关联属性:publish) --------------> Publish
                        <---------------
                          publish_obj.book_set.过滤方法() # 一般选择QuerySet返回值的方法???


多对多查询
    正向查询:通过A查询B,正向查询按 字段
    反向查询:通过B查询A  反向查询按 表名_set  一般使用 表名_set.all() 方法
                          book_obj.authors.all()
    Book(关联属性:authors) --------------> Authors
                        <---------------
                         author_obj.book_set.all()


一对一查询
    正向查询:通过A查询B,正向查询按 字段
    反向查询:通过B查询A  反向查询按 表名小写(没有_set了)
            应为是一对一的关系,所以反向查找的只有一个
                                  author_obj.authordetail
    Author(关联属性:authordetail) --------------> AuthorDetail
                               <---------------
                               authordetail.author
"""

注意:

你可以通过在 ForeignKey() 和ManyToManyField的定义中设置 related_name 的值来覆写 FOO_set 的名称。例如,如果 Article model 中做一下更改:

publish = ForeignKey(Book, related_name='bookList')

那么接下来就会如我们看到这般:

# 查询 人民出版社出版过的所有书籍

publish=Publish.objects.get(name="人民出版社")
book_list=publish.bookList.all()  # 与人民出版社关联的所有书籍对象集合

posted @ 2018-07-21 11:25  哈哈大圣  阅读(190)  评论(0编辑  收藏  举报