関連する知識のジャンゴday04ベース----


from django.test import TestCase

# Create your tests here.

'''
当你想单独测试django中某一个py文件时,你需要手动配置测试文件
在manage.py文件中拷贝前四行代码,另外再加三行代码
添加:
    import django
    django.setup()
    from app01 import models
    
'''
import os
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")
    import django

    django.setup()
    from app01 import models

####################add增、set改、remove移除、clear清空四个方法的使用###################

# 一对多字段数据的增删改查

    # 增
    # models.Book.objects.create(title='三国演义',price=222.33,publish_id=1)
    '''
    方法:
        第一种.传实际字段,利用publish_id=1,直接传表里面的实际字段,对应更新到数据库中
        第二种.虚拟字段传数据对象,通过虚拟字段,利用对象来创建
    
    '''
    # publish_obj=models.Publish.objects.filter(pk=2).first()
    # models.Book.objects.create(title='红楼梦',price=444.33,publish=publish_obj)

    # 查

    # 改
    # 第一种    传实际字段
    # models.Book.objects.filter(pk=1).update(publish_id=2)
    # django中默认id作为主键,此处代表查询主键id=1的数据,pk=1 等同于 id=1
    # update(表中字段A = 字段值B)

    # 第二种    虚拟字段传数据对象
    # publish_obj=models.Publish.objects.filter(pk=1).first()
    # models.Book.objects.filter(pk=1).update(publish=publish_obj)

    # 删  (知道即可,工作中不要使用)
    # 默认的是级联删除、级联更新
    # models.Publish.objects.filter(pk=3).delete()

# 多对多字段数据的增删改查

# 增(add)
#     方法一:(传数字)
#     方法二:(传对象)


    # book_obj=models.Book.objects.filter(pk=2).first()
    # 给当前这一本书绑定作者
    # 1.手动添加---绝对不推荐
    # 2.通过对象点属性【自我理解为:对象点虚拟字段-->直接进入第三张表】-->跨到第三张表
    # print(book_obj.publish)       #北方出版社
    # print(book_obj.authors)     #app01.Author.None
    # book_obj.authors.add(1)     #在第三张表里面给书籍id=2的添加一个author_id=1 的作者

    # 【自我理解为:对象点虚拟字段-->是直接进入第三张表】
    '''
    结果就是:
    id  book_id  author_id
     1      2       1
    '''
    # book_obj.authors.add(1,2)   #在第三张表里面给书籍id=2的添加两个作者,
    # 一个是author_id=1的作者,另一个是author_id=2的作者

    '''
   结果就是:
   id  book_id  author_id
    1      2       1
    2      2       2    
    '''
    # book_obj = models.Book.objects.filter(pk=2).first()
    # author_obj=models.Author.objects.filter(pk=1).first()
    # author_obj1=models.Author.objects.filter(pk=2).first()
    # # book_obj.authors.add(author_obj)
    # book_obj.authors.add(author_obj,author_obj1)

    '''
    方法一:(传数字)
        add方法   能够朝第三张关系表添加数据
            即支持传数字
                add(1,2)
            
            也支持传对象
                add(author_obj,author_obj100)
            
            并且无论是传数字还是传对象都是可以传多个值
    
    
    '''

    '''
方法二:(传对象)
    book_obj = models.Book.objects.filter(pk=2).first()
    author_obj=models.Author.objects.filter(pk=1).first()
    book_obj.authors.add(author_obj)
    
    # 【第三句自我理解为:对象点虚拟字段-->是直接进入到第三张表关系表】
        book_obj.authors.add(author_obj)
        
    这里面是通过book_obj对象点Book表中的虚拟字段authors,直接进入到
    第三张书籍与作者的book_authors关系表,然后添加了Author作者表
    pk为1的对象
        
        对于Book表中虚拟字段authors最通俗的介绍就是:牵线红娘
    帅哥          通过红娘(authors)           美女     
    单身        ------------------------>      漂亮  
                     
单身帅哥book_obj通过通过红娘(authors添加了(add)漂亮美女,组成了一个家庭。
结果就是:
   id  book_id  author_id
    1      2       1

    
    '''

# 改(set,注意set(这里还有一个括号()))
    #方法一:传数字
    #方法二:(传对象)

# 方法一:传数字
#     book_obj=models.Book.objects.filter(pk=2).first()
#             book_obj.authors.set((1,3))
'''
TypeError: set() takes 2 positional arguments but 3 were given
set()必须是一个可以迭代的对象,可以迭代的对象有:元祖、列表、字典、集合、字符串
使用set其实是先在数据库中删除对应的数据,然后再增加对应的数据
set()----set里面必须得传一个可以迭代的对象,不然会报错,
例如:book_obj.authors.set(1)
TypeError:'int' object is not iterable
整形不是可以迭代的对象

book_obj=models.Book.objects.filter(pk=2).first()
book_obj.authors.set('33')
如果set字符串33的话,
表中的数据只有一个结果,就是除了author_id=3的,
别的(author_id=1和author_id=2)都没了,
结果就是:
   id  book_id  author_id
    1      2       3
**********************************************************          
book_obj = models.Book.objects.filter(pk=2).first()
book_obj.authors.set((1, 3))
# 在第三张表里面给书籍book_id=2的字段【重新设置】两个作者id,
# 一个是author_id=1的作者,另一个是author_id=2的作者

# 该方法有漏洞,如果book_id=2对应的作者id有5个,那么set((1,3)),
# 就会出问题了,一旦执行代码,
就会把book_id=2对应的author_id=2和author_id=4,和author_id=5的数据删除掉


'''
# book_obj = models.Book.objects.filter(pk=2).first()
# book_obj.authors.set((1, 3))

# 方法二:(传对象)
#     book_obj=models.Book.objects.filter(pk=2).first()
#
#     author_obj01=models.Author.objects.filter(pk=1).first()
#     author_obj02=models.Author.objects.filter(pk=2).first()
#     book_obj.authors.set((author_obj01,author_obj02))
#
'''
set修改多对多关系表中的数据
    既可以传数字也可以传对象
    但是需要注意的是括号内必须是可迭代对象
    同样都支持多个数字和对象
        set((1,3))
        set((author_obj,author_obj02))

'''


#删除
#移除一个
#在book_authors表中移除author_id=1的数据
# book_obj=models.Book.objects.filter(pk=2).first()
# book_obj.authors.remove(1)
'''
结果就是:
   id  book_id  author_id
    1      2       2
    
'''
#移除多个
# book_obj=models.Book.objects.filter(pk=2).first()
# book_obj.authors.remove(1,2)

'''
结果就是:
   id  book_id  author_id
    1      2       3

'''
#传单个对象
# book_obj=models.Book.objects.filter(pk=2).first()

# author_obj01=models.Author.objects.filter(pk=1).first()
# author_obj02=models.Author.objects.filter(pk=2).first()

# book_obj.authors.remove(author_obj01)
#传多个对象
# book_obj.authors.remove(author_obj01,author_obj02)
'''
remove 既可以传数字,也可以传对象
    并且都支持传多个值,不需要迭代
        remove(1,2)
        remove(author_obj01,author_02) 

'''

#清空表数据       删除某个数据在第三张表中的所有记录
# book_obj=models.Book.objects.filter(pk=2).first()
# book_obj.authors.clear()
'''
clear 清空书籍相关所有记录,括号内不需要传任何参数。
'''

############################ 跨表查询##############################
#------------------情况01.基于对象的跨表查询----对应MySQL中的子查询,【子查询,分步操作】

# 什么是子查询,就是将一张表的查询结果,作为另一张表的查询条件
'''
正反向查询:
    A表(有外键关联到B表)       B表
    关系字段在谁哪?由谁查谁就是正向,
    关系字段在A那,由A查B是正向----称之为正向查询
                   由B查A是反向-----称之为反向查询
    
    正向查询按字段
    反向查询按表名小写_set
    
'''
#1.查询书籍主键为2的出版社名称
#    书查出版社是正向查询,按字段
# book_obj=models.Book.objects.filter(pk=2).first()
# print(book_obj.publish)         #    出版社对象
# print(book_obj.publish.name)    #    打印结果:北方出版社

#2.查询书籍主键为4的作者姓名
#    书查作者是正向查询,按字段
# book_obj=models.Book.objects.filter(pk=4).first()
# print(book_obj.authors)     #标志性结果app01.Author.None,不代表代码错误,仅仅是少了一个 .all()
# print(book_obj.authors.all())   #<QuerySet [<Author: oscar>, <Author: egon>]>

#3.查询作者是jason的手机号码
# #这个是问题代码,原因是由于在models中的Author表建立表与表关系的时候,写错了一个单词
# author_obj=models.Author.objects.filter(name='jason').first()
# res = models.Author.objects.filter(name='jason')
# print(author_obj)
# print(author_obj.author_detail.phone)       #结果:110

'''
什么时候需要加all
当正向查询点击外键字段数据有多个的情况下,需要 .all()比如,一本书多个作者
当反向查询点击表名小写_set之后有多个值的情况下,需要 .all() 查询所有
标志性结果app01.Author.None  一旦看到该结果,只需要加.all()即可


在写orm语句的时候,跟你写sql语句一样,不要想着一次性写完,
写一点差一点再写一点


'''

#4.查询出版社是东方出版社出版过的书籍,并且打印书籍的名称
#  通过出版社查书籍是反向查询,反向查询表名小写_set
# publish_obj=models.Publish.objects.filter(name='东方出版社').first()
# print(publish_obj.book_set)             #app01.Book.None
# print(publish_obj.book_set.all())       #<QuerySet [<Book: Book object>, <Book: Book object>]>
# book=publish_obj.book_set.all()         #<QuerySet [<Book: Book object>, <Book: Book object>]>
#QuerySet,用for循环取列表中的对象,通过print(对象.属性),获取对应的值
# for i in book:
#     print(i.title)      #三国演义、水浒传

#5.查询作者是jason写过的书籍
#   通过作者查书籍是反向查询,反向查询表名小写_set
# author_obj=models.Author.objects.filter(name='jason').first()
# print(author_obj.book_set)          #app01.Book.None
# print(author_obj.book_set.all())    #<QuerySet [<Book: Book object>, <Book: Book object>]>

#6.查询手机号是120的作者姓名
#作者详情查作者,反向查询,表名小写_set
# author_detail_obj=models.AuthorDetail.objects.filter(phone=120).first()
# print(author_detail_obj.author)
# print(author_detail_obj.author.email)   #[email protected]
# print(author_detail_obj.author.name)    #oscar
'''
反向查询 :
什么时候表名加  _set,总结:
    当你反向查询的数据是多个的时候就需要表名加上  _set,
    当你反向查询的数据是一个的时候就不需要加  _set

专业总结术语如下:
    
    查询的表关系中外键上书写的是 一对多、多对多的情况需要加  _set
    查询的表关系中外键上书写的是一对一,这种情况不需要加  _set
    
    一对多:ForeignKey      (django中没有OneToManyField)
    多对多:ManyToManyField
    一对一:OneToOneField

'''


#---------------------情况02.基于双下划线的跨表查询      联表操作
'''
inner join
left join
right join
union

'''

#***************双下划线的跨表查询**************重点中的重点优先掌握************************
'''
values方法总结:
values('publish__name')
values中写外键字段就相当于已经跨到了外键字段所关联的表
你想要该表中的哪个字段,只需要双下字段名(__name)获取即可
'''

#1.查询书籍pk为2的出版社名称
#       正向
# res=models.Book.objects.filter(pk=2).values('publish__name')
# values中publish一写,就代表已经跳转到了Publish这张表,然后双下name来取字段的值
#需要注意的是values里面有引号,自己总是忘记写
# print(res)        #<QuerySet [{'publish__name': '北方出版社'}]>

'''         filter()括号里面既支持正向,同时也支持反向   '''
#       反向
# print(models.Publish.objects.filter(book__pk=2))    #<QuerySet [<Publish: 北方出版社>]>
# res=models.Publish.objects.filter(book__pk=2).values('name')
# print(res)      #<QuerySet [{'name': '北方出版社'}]>


#2.查询书籍pk为2的作者姓名
#           正向
# res=models.Book.objects.filter(pk=2).values('authors__name')
# print(res)    #<QuerySet [{'authors__name': 'jason'}, {'authors__name': 'oscar'}]>
#   查询书籍pk为2的作者姓名和邮箱
# res=models.Book.objects.filter(pk=2).values('authors__name','authors__email')
# print(res)
#打印结果<QuerySet [{'authors__name': 'jason', 'authors__email': '[email protected]'}, {'authors__name': 'oscar', 'authors__email': '[email protected]'}]>

#           反向
# res=models.Author.objects.filter(book__pk=2).values('name')
# print(res)       #<QuerySet [{'name': 'jason'}, {'name': 'oscar'}]>
#
# res=models.Author.objects.filter(book__pk=2).values('name','email')
# print(res)
#打印结果<QuerySet [{'name': 'jason', 'email': '[email protected]'}, {'name': 'oscar', 'email': '[email protected]'}]>


#3.查询作者是egon的家庭地址
#               正向
# res=models.Author.objects.filter(name='egon').values('author_detail__addr')
# print(res)      #<QuerySet [{'author_detail__addr': '山东'}]>

#               反向
# res=models.AuthorDetail.objects.filter(author__name='egon').values('addr')
# print(res)          #<QuerySet [{'addr': '山东'}]>


#4.查询出版社是东方出版社出版过的书的名字
#               正向
# res=models.Publish.objects.filter(name='东方出版社').values('book__title')
# print(res)      #<QuerySet [{'book__title': '三国演义'}, {'book__title': '水浒传'}]>

#               反向
# res=models.Book.objects.filter(publish__name='东方出版社').values('title')
# print(res)      #<QuerySet [{'title': '三国演义'}, {'title': '水浒传'}]>


#最复杂之orm查询,查询书籍pk=2的作者的手机号
#               正向
# res=models.Book.objects.filter(pk=2).values('authors__author_detail__phone')
# print(res)  #<QuerySet [{'authors__author_detail__phone': 110}, {'authors__author_detail__phone': 120}]>

#               反向
# res=models.Author.objects.filter(book__pk=2).values('author_detail__phone')
# print(res)
#打印结果:<QuerySet [{'author_detail__phone': 110}, {'author_detail__phone': 120}]>





おすすめ

転載: www.cnblogs.com/ludundun/p/11955525.html