Django框架06 /orm多表操作

1. admin相关操作

  • 注册超级用户

    python manage.py createsuperuser
    
    # 输入用户名:liubing
    # 邮箱不用输 直接回车
    # 输入密码:必须超过8位,并且别太简单
  • 在admin文件中注册orm表

    from django.contrib import admin
    from app01 import models admin.site.register(models.Author)
    admin.site.register(models.AuthorDetail)
    admin.site.register(models.Publish)
    admin.site.register(models.Book) # 在admin页面设置可编辑
    from django.contrib import admin
    from sales import models class UserInfoAdmin(admin.ModelAdmin):
    list_display = ['id','username','telephone'] class CourseRecordAdmin(admin.ModelAdmin):
    list_display = ['id','day_num','course_title','re_class','teacher']
    list_editable = ['day_num','course_title','re_class','teacher',] class StudyRecordAdmin(admin.ModelAdmin):
    list_display = ['id','attendance','score','student',]
    list_editable = ['attendance','score','student',] admin.site.register(models.UserInfo,UserInfoAdmin)
    admin.site.register(models.Department)
    admin.site.register(models.ClassList)
    admin.site.register(models.Campuses)
    admin.site.register(models.Customer)
    admin.site.register(models.ConsultRecord)
    admin.site.register(models.StudyRecord,StudyRecordAdmin)
    admin.site.register(models.Enrollment)
    admin.site.register(models.CourseRecord,CourseRecordAdmin)

2. 创建模型

  • 表和表之间的关系

    • 一对一
    • 多对一
    • 多对多
  • 简单表关系构建

    1.作者模型:一个作者有姓名和年龄。
    
    2.作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一的关系(one-to-one)
    
    3.出版商模型:出版商有名称,所在城市以及email。
    
    4.书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。
  • 代码实现:

    from django.db import models
    
    # 作者表
    class Author(models.Model):
    # id可以省略不写,默认id为主键自增
    # id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    authorDetail = models.OneToOneField(to='AuthorDetail',to_field='id',on_delete=models.CASCADE)
    on_delete=models.CASCADE
    # Django 1.把版本默认就是,Django 2.版本没有需要自己需要时设置
    # 简写
    # authorDetail=models.OneToOneField("AuthorDetail",on_delete=models.CASCADE) # 作者明细表
    class AuthorDetail(models.Model):
    # id = models.AutoField(primary_key=True)
    birthday = models.DateField()
    # 电话字段选择CharField类型,如果查找以'151'开头的话,整型不能实现
    telephone = models.CharField(max_length=20)
    addr = models.CharField(max_length=64) # 出版社表
    class Publish(models.Model):
    # id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField() # 书籍表
    class Book(models.Model):
    # id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    publishDate = models.DateField()
    price = models.DecimalField(max_digits=5,decimal_places=2) # 多对一
    # publish = models.ForeignKey(to='Publish',to_field='id',on_delete=models.CASCADE)
    # 简写
    publishs=models.ForeignKey(to="Publish",on_delete=models.CASCADE,) # 多对多
    # authors = models.ManyToManyField(to='Author',)
    # 简写
    authors=models.ManyToManyField('Author',)
  • 元信息

    • ORM对应的类里面包含另一个Meta类,而Meta类封装了一些数据库的信息。
    class Author2Book(models.Model):
    author = models.ForeignKey(to="Author")
    book = models.ForeignKey(to="Book")
    class Meta:
    db_table='authordetail' # 指定表名
    index_together= ("author", "book") # 创建联合索引
    unique_together = ("author", "book") # 创建联合唯一索引
    ordering = ['-id',] # 按id字段排序 db_table
    # ORM在数据库中的表名默认是 app_类名,可以通过db_table可以重写表名。db_table = 'book_model' index_together
    # 联合索引。 unique_together
    # 联合唯一索引。 ordering
    # 指定默认按什么字段排序。
    ordering = ['id',]
    # 只有设置了该属性,我们查询到的结果才可以被reverse(),否则是能对排序了的结果进行反转(order_by()方法排序过的数据)

3. 增加

  • 代码示例

    def test(request):
    # 一对一
    au_obj = models.AuthorDetail.objects.get(id=4) models.Author.objects.create(
    name = 'song',
    age = 59, # 方式一
    authorDetail=au_obj,
    # 方式二
    authorDetail_id=4
    ) # 一对多
    pub_obj = models.Publish.objects.get(id=3) models.Book.objects.create(
    title = 'python',
    publishDate='2016-6-6',
    price = 88,
    # 方式一:
    publish = pub_obj # 方式二:
    publish_id = 3
    ) # 多对多
    a1 = models.Author.objects.get(id=1)
    a2 = models.Author.objects.get(id=4)
    new_obj = models.Book.objects.create(
    title = '老人与海',
    price = 99,
    publishDate='2019-1-1',
    publish_id=2,
    )
    # 方式一(常用):
    new_obj.authors.add(*[1,4]) # *args,**kwargs
    # 方式二:
    new_obj.authors.add(1,4)
    # 方式三:
    new_obj.authors.add(a1,a2)

4. 删除

  • 代码示例

    # 一对一
    # 先删除关联表,再删除被关联表,否则就是级联删除
    models.Author.objects.filter(id=3).delete()
    models.AuthorDetail.objects.filter(id=3).delete() # 一对多
    models.Book.objects.filter(id=3).delete()
    models.Publish.objects.filter(id=3).delete() # 多对多 --- 删除第三张表、关联两两张表的中间表
    book_obj = models.Book.objects.get(id=2)
    book_obj.authors.remove(1) #删除 id=2的book表对应的id=1的Author的第三张表的记录
    book_obj.authors.clear() #清除
    book_obj.authors.set(['1','5']) #先清除再添加,相当于修改,列表里的id值必须用引号引起来

5. 修改

  • 代码示例

    ret = models.Publish.objects.get(id=2)
    models.Book.objects.filter(id=5).update(
    title = 'linux',
    # 方式一:
    publish =ret,
    # 方式二:
    publish_id = 1,
    ) # 修改 --- models对象不能使用update方法

6. 基于对象的跨表查询

  • 代码示例

    # 一对一
    
    # 正向查询  -- 对象.属性
    # 关系属性写在表1,关联到表2,那么通过表1的数据去找表2的数据,叫做正向查询,反过来就是反向查询 # 查询一下song的电话号码
    obj = models.Author.objects.filter(name='song').first()
    te = obj.authorDetail.telephone
    print(te) # 反向查询 -- 对象.小写表名
    # 查一下电话号码为110的作者姓名
    obj = models.AuthorDetail.objects.filter(telephone=110).first()
    na = obj.author.name
    print(na) # 一对多
    # 正向查询
    # 查询老人与海这本书是哪个出版社出版的
    obj = models.Book.objects.filter(title='老人与海').first()
    te = obj.publish.name
    print(te) # 反向查询
    # 查询24出版社出版过哪些书
    obj = models.Publish.objects.filter(name='24出版社').first()
    ret = obj.book_set.all()
    # print(ret) #<QuerySet [<Book: python>]> # 循环取值
    for i in ret:
    print(i.title) #python # 多对多 # 正向查询
    # 老人与海 是哪些作者写的
    obj = models.Book.objects.filter(title='老人与海').first()
    ret = obj.authors.all()
    print(te) #<QuerySet [<Author: liu>, <Author: song>]> # 循环取值
    for i in ret:
    print(i.name) #liu song # 反向查询
    # 查询一下song写了哪些书
    obj = models.Author.objects.filter(name='song').first()
    ret = obj.book_set.all()
    print(ret) #<QuerySet [<Book: 老人与海>]> # 循环取值
    for i in ret:
    print(i.title) #老人与海
    print(i.publish.name) #北大出版社 # 总结:
    # 通过数据库字段增删改的话,对应写的是对应的id值
    # 通过类的属性增删改的话,对应写的是对应的对象

7. 基于双下划线的跨表查询 -- 基于join实现的

  • 双下划线方法查询概述

    • Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系。要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的model 为止。
    • 基于双下划线的查询就一句话:正向查询按字段,反向查询按表名小写用来告诉ORM引擎join哪张表,一对一、一对多、多对多都是一个写法,注意,我们写orm查询的时候,哪个表在前哪个表在后都没问题,因为走的是join连表操作。
  • 正向查询和反向查询

    # 一对一
    # 1. 查询二狗的电话号
    # 方式1 正向查询
    obj = models.Author.objects.filter(name='二狗').values('authorDetail__telephone')
    print(obj) #<QuerySet [{'authorDetail__telephone': '888'}]>
    # 方式2 反向查询
    obj = models.AuthorDetail.objects.filter(author__name='二狗').values('telephone','author__age')
    print(obj) #<QuerySet [{'telephone': '888'}]> # 2. 哪个老师的电话是88
    # 方式1 正向查询
    obj = models.Author.objects.filter(authorDetail__telephone='888').values('name')
    print(obj)
    # 方式2 反向查询
    obj = models.AuthorDetail.objects.filter(telephone='888').values('author__name')
    print(obj) # 一对多
    # 1.查询一下李老头的故事这本书的出版社是哪个
    # 方式1 正向查询
    obj = models.Book.objects.filter(title='李老头的故事').values('publishs__name')
    print(obj) #<QuerySet [{'publishs__name': '李老头出版社'}]> # 方式2 反向查询
    obj = models.Publish.objects.filter(book__title='李老头的故事').values('name')
    obj = models.Publish.objects.filter(xx__title='李老头的故事').values('name')
    print(obj) # 2.李老头出版社出版了哪些书
    # 方式1 反向查询
    obj = models.Publish.objects.filter(name='李老头出版社').values('book__title')
    print(obj) #<QuerySet [{'book__title': '李老头的故事'}, {'book__title': '李老头的故事2'}]> # 方式2 正向查询
    obj = models.Book.objects.filter(publishs__name='李老头出版社').values('title')
    print(obj) #<QuerySet [{'title': '李老头的故事'}, {'title': '李老头的故事2'}]> # 多对多
    # 1.李老头的故事这本书是谁写的
    # 方式1 正向查询
    obj = models.Book.objects.filter(title='李老头的故事').values('authors__name')
    print(obj) # 方式2 反向查询
    obj = models.Author.objects.filter(book__title='李老头的故事').values('name')
    print(obj) #<QuerySet [{'name': '大狗'}, {'name': '二狗'}]> # 2.大狗写了哪些书
    # 方式1 正向查询
    obj = models.Book.objects.filter(authors__name='大狗').values('title')
    print(obj) # 方式2 反向查询
    obj = models.Author.objects.filter(name='大狗').values('book__title')
    print(obj) # 进阶的
    # 多表联查
    # 1.李老头出版社 出版的书的名称以及作者的名字
    obj = models.Book.objects.filter(publishs__name='李老头出版社').values('title','authors__name')
    print(obj)
    #结果:<QuerySet [{'title': '李老头的故事', 'authors__name': '大狗'}, {'title': '李老头的故事', 'authors__name': '二狗'}, {'title': '李老头的故事2', 'authors__name': '二狗'}, {'title': '李老头的故事2', 'authors__name': '三狗'}]>
    '''
    sql语句:
    SELECT app01_book.title,app01_author.name from app01_publish INNER JOIN app01_book on app01_publish.id=app01_book.publishs_id
    INNER JOIN app01_book_authors on app01_book.nid = app01_book_authors.book_id INNER JOIN app01_author
    ON app01_author.id = app01_book_authors.author_id where app01_publish.name='李老头出版社';
    :param request:
    :return:
    ''' obj = models.Publish.objects.filter(name='李老头出版社').values('book__title','book__authors__name')
    print(obj) obj = models.Author.objects.filter(book__publishs__name='李老头出版社').values('name','book__title')
    print(obj) # authorDetail author book publish
    # 2.手机号以4开头的作者出版过的所有书籍名称以及出版社名称
    ret = models.AuthorDetail.objects.filter(telephone__startswith='4').values('author__book__title','author__book__publishs__name')
    print(ret)
    #QuerySet [{'author__book__title': '李老头的故事', 'author__book__publishs__name': '李老头出版社'}, {'author__book__title': '李老头的故事2', 'author__book__publishs__name': '李老头出版社'}]> # 3.查询一下李老头出版社出版了哪些书
    obj = models.Publish.objects.filter(name='李老头出版社').first()
    print(obj.xx.all())
  • related_name

    publish = ForeignKey(Blog, related_name='bookList')
    
    # 反向查询时,如果定义了related_name ,则用related_name替换 表名

8. Python脚本中调用Django 环境(Django外部脚本使用models)

  • 如果你想通过自己创建的python文件在django项目中使用django的models,那么就需要调用django的环境

    import os
    if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
    import django
    django.setup()
    from app01 import models #引入也要写在上面三句之后
    books = models.Book.objects.all()
    print(books)

Django框架06 /orm多表操作的更多相关文章

  1. Django框架05 /orm单表操作

    Django框架05 /orm单表操作 目录 Django框架05 /orm单表操作 1. orm使用流程 2. orm字段 3. orm参数 4. orm单表简单增/删/改 5. orm单表查询 5 ...

  2. django框架基础-ORM单表操作-长期维护

    ###############    单表操作-添加数据    ################ import os if __name__ == '__main__': os.environ.set ...

  3. django框架基础-ORM跨表操作-长期维护

    ###############    一对一跨表查询    ################ import os if __name__ == '__main__': os.environ.setde ...

  4. Django之模型---ORM 多表操作

    多表操作 创建表模型 from django.db import models # Create your models here. class Author(models.Model): nid = ...

  5. Django框架之ORM对表结构操作

    ORM的优点:(1)简单,不用自己写SQL语句 (2)开发效率高 ORM的缺点:对于不同的人写的代码,执行效率有差别 ORM的对应关系: 类  ---------->  数据表 对象------ ...

  6. Django视图之ORM连表操作一

    1 项目路径结构树 2 models创建类 from django.db import models class UserType(models.Model): ''' 用户类型 ''' title ...

  7. Django之模型---ORM 单表操作

    以上一随笔中创建的book表为例讲解单表操作 添加表记录 方式一 # create方法的返回值book_obj就是插入book表中的python葵花宝典这本书籍纪录对象 book_obj=Book.o ...

  8. python django基础五 ORM多表操作

    首先在创建表的时候看下分析一下 1.作者表和作者详细地址表  一对一关系 理论上谁都能当主表 把Author设置成主表 au=models.OneToOneField(to='AuthorDetail ...

  9. Django 学习 之ORM多表操作

    一.创建模型 1.模型关系整理 创建一对一的关系:OneToOne("要绑定关系的表名") 创建一对多的关系:ForeignKey("要绑定关系的表名") 创建 ...

随机推荐

  1. 安装并配置Samba

    1. 安装 samba ~$sudo apt-get install samba 2. 修改 samba 的配置文件 ~$sudo gedit /etc/samba/smb.conf 添加如下内容 [ ...

  2. List作为泛型参数实现可接收存储任意类型的List对象

    原文链接:https://blog.csdn.net/eeeeasy/article/details/80999650?utm_source=blogxgwz2 在项目中遇到一个问题,想要封装一个通用 ...

  3. 恕我直言你可能真的不会java第1篇:lambda表达式会用了么?

    本文配套教学视频:B站观看地址 在本号之前写过的一些文章中,笔者使用了lambda表达式语法,一些读者反映说代码看不懂.本以为java 13都已经出了,java 8中最重要特性lambda表达式大家应 ...

  4. 深入理解JVM(③)低延迟的Shenandoah收集器

    前言 Shenandoah作为第一款不由Oracle(包括一起的Sun)公司的虚拟机团队所领导开发的HotSpot垃圾收集器.是只存在于OpenJDK当中的,最初由RedHat公司创建的,在2014年 ...

  5. Flask框架基础功能

    引言 本文简单汇总Flask框架几大基础功能,包括: 路由系统 模板 数据库 几种常用Flask库 一个简单的Flask事例 Flask是一个基于Python,依赖Jinja2模板和WSGI服务的框架 ...

  6. 使用本地http的yum源

    使用http作为本地yum源 场景 在生产环境中,有大概好几十台linux同系统版本的操作系统,为了安装普通软件,现在的做法是向每台机器上上传一个iso镜像,然后将镜像挂在,配置本地的yum源,实现基 ...

  7. 运行 docker .... 命令报错

    一.检查 Linux 上是有存在 docker [root@localhost bin]# docker version 不存在 docker 时,可以使用如下命令下载 docker [root@lo ...

  8. Struts2 执行流程 以及 Action与Servlet比较 (个人理解)

    上图提供了struts2的执行流程.如下: 1:从客户端发出请求(HTTPServletRequest). 2:请求经过各种过滤器(filter),注:一般情况下,如SiteMesh等其他过滤器要放在 ...

  9. 观察者模式(Observer Pattern)(二):HeadFirst中的气象站的实现

    1 观察者模式的原理,首先由一个主题,当主题发送变化的时候,通知该主题的订阅者 按照上面的分析我们来进行设计 1.抽象主题Subject public interface Subject { publ ...

  10. 谈反应式编程在服务端中的应用,数据库操作优化,提速 Upsert

    反应式编程在客户端编程当中的应用相当广泛,而当前在服务端中的应用相对被提及较少.本篇将介绍如何在服务端编程中应用响应时编程来改进数据库操作的性能. 开篇就是结论 接续上一篇<谈反应式编程在服务端 ...