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. (四)MySQL条件查询(通配符、模糊查询)、排序查询、分组查询(单行、分组函数)

    一.条件查询 1.含义:前面学的基础查询可以查询一个或多个字段,如果需要的数据仅仅是其中的某一行或多行就用到了条件查询. 2.语法:(序号表示语句执行顺序) SELECT 字段名 ③ FROM 表名 ...

  2. (四)Parameters,简单参数就用这个

    Parameters注解在测试方法上指定参数列表,然后在测试方法中声明对应的形参,形参与参数列表一一对应,但名字可以不同,如下所示: public class Test1 { @Parameters( ...

  3. 使用python求解向量值函数的雅各比(Jacobian)矩阵

    考虑一个向量值函数$R^m \rightarrow R^n$,即$\textbf{y} = f(\textbf{x})$,它的雅各比(Jacobian)矩阵定义如下. 下面记录下一段使用python求 ...

  4. 国外一教授坦言,用这方法能迅速成为python程序员,但都不愿意说_编程小十

    越来越多的人学习python,但你学习python用了多长的时间?#Python# 你知道如何才能迅速掌握并成为python程序员吗?   有这样的一位国外的教授说,要迅速成为python程序员,几乎 ...

  5. 一文读懂:GBDT梯度提升

    先缕一缕几个关系: GBDT是gradient-boost decision tree GBDT的核心就是gradient boost,我们搞清楚什么是gradient boost就可以了 GBDT是 ...

  6. mysql 出现You can't specify target table for update in FROM clause错误的解决方法

    mysql出现You can’t specify target table for update in FROM clause 这个错误的意思是不能在同一个sql语句中,先select同一个表的某些值 ...

  7. 微信小程序navigator带参数跳转及接收参数内容

    // index.wxml <navigator class='looks-view' wx:for="{{imgUrlNew}}" wx:key="index&q ...

  8. 关于对Entity Framework 3.1的理解与总结

    Entity Framework Core 是一个ORM,所谓ORM也是ef的一个框架之一吧,简单的说就是把C#一个类,映射到数据库的一个表,把类里面的属性映射到表中的字段.然后Entity Fram ...

  9. postman写测试用例

    接口测试引用聚合数据(手机号码归属地)接口 1,点击postman左上角红框+New Collection来创建文件,用来存放测试用例 文件名为号码归属地查询(随意)  2,右击文件选择Add Req ...

  10. 入门大数据---HDFS-API

    第一步:创建一个新的项目 并导入需要的jar包 公共核心包 公共依赖包 hdfs核心包 hdfs依赖包 第二步:将Linux中hadoop的配置文件拷贝到项目的src目录下 第三步:配置windows ...