zoukankan      html  css  js  c++  java
  • Django模型层之多表操作

    一、创建多表模型

    实例:

    作者表:
        拥有字段:姓名(name),性别(sex),该表与书籍表之间为多对多的关系
    作者详情表:
        拥有字段:地址(addr),手机号(phone),该表与作者表之间为一对一的关系
    出版社表:
        拥有字段:名字(name),地址(addr),该表与书籍表之间为一对多的关系
    书籍表:
        拥有字段:书名(name),单价(price)
    分析:一本书可以拥有多个作者,一个作者可以写多本书,所有作者与书籍之间为多对多的关联关系(Many-To-Many);一本书只有一个出版社,但是一个出版社可以出版多种书籍,所以出版社和书籍之间是一对多的关联关系(One-To-Many);作者与作者详情就是一对一关联关系(One-To-One)

    在models.py下创建模型如下:

    class Publish(models.Model):
        name = models.CharField(max_length=255)
        addr = models.CharField(max_length=255)
    
        def __str__(self):
            return self.name
    
    
    class Author(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=255)
        sex = models.IntegerField()
        authordetail = models.OneToOneField(to='AuthorDetail')
    
        def __str__(self):
            return self.name
    
    
    class AuthorDetail(models.Model):
        id = models.AutoField(primary_key=True)
        addr = models.CharField(max_length=255)
        phone = models.CharField(max_length=255)
    
    
    class Book(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=255)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        # 外键,关联关系写在一对多中多的那一方
        publish = models.ForeignKey(to=Publish)
        authors = models.ManyToManyField(to=Author)
    
        def __str__(self):
            return self.name

    注意事项;

    1.id字段不写的话会自动添加
    2.对于外键字段,Django会在字段名上添加"_id"来创建数据库中的列名
    3.外键字段ForeignKey有一个null=True的设置,你可以赋给它空值None

    二、添加表记录

    一对一:

    # 方式一:
    detail_obj = models.AuthorDetail.objects.filter(id=2).first()
    models.Author.objects.create(name='Yven',sex=1,authordetail=detail_obj)
    
    # 方式二:
    models.Author.objects.create(name='hwt',sex=2,authordetail_id=1)

    一对多:

    # 方式一:
    publish_obj = models.Publish.objects.filter(id=2).first()
    models.Book.objects.create(name='水浒传',price=24.5,publish=publish_obj)
    
    # 方式二:
    models.Book.objects.create(name='西游记',price=24.5,publish_id=2)

    多对多:

    # 获得书籍对象
    book = models.Book.objects.create(name='水浒传',price=24.5,publish_id=3)
    # 获得作者对象
    yven = models.Author.objects.get(name='Yven')
    hwt = models.Author.objects.get(name='hwt')
    
    # 绑定多对多关系
    # add中可以传递对象,可以传递id,也可以传递*列表如:(*[yven,hwt])
    book.authors.add(yven,hwt)
    
    #多对多关系其他常用API:
    # 将某个特定的对象从被关联对象集合中去除,可以传递对象,可以传递id,也可以传递*列表如:(*[yven,hwt])
    book.authors.remove()
    # 清空被关联对象集合,无需传参
    book.authors.clear()
    # 先清空再设置,传递的参数必须是可迭代对象,一般为列表,列表内可以是对象,也可以是id
    book.authors.set()

    三、基于对象的跨表查询

    一对一:

    #正向:关联字段在哪里,从哪里开始就是正向。正向查询按字段
    #查询小明作者的手机号
    author = models.Author.objects.filter(name='小明').first()
    authordetail = author.authordetail#authordetail是字段名
    print(authordetail.phone)
    
    #反向:反向查询按表名小写
    #查询地址是北京的作者名字
    authordetail = models.AuthorDetail.objects.filter(addr='北京').first()
    author = authordetail.author#author是表名
    print(author.name)

    一对多:

    #正向:正向查询按字段
    # 查询红楼梦这本书的出版社邮箱
    book = models.Book.objects.filter(name='红楼梦').first()
    publish = book.publish
    print(publish.email)
    
    #反向:反向按表名小写_set.all()
    # 查询地址是北京 的出版社出版的图书
    publish = models.Publish.objects.filter(addr='北京').first()
    book = publish.book_set.all()
    print(book)

    多对多:

    #正向:正向查询按字段.all()
    #查询红楼梦这本书所有的作者
    book = models.Book.objects.filter(name='红楼梦').first()
    author = book.authors.all()
    print(author)
    
    #反向查询:反向按表名小写_set.all()
    #查询小明写的所有书
    author = models.Author.objects.filter(name='小明').first()
    book = author.book_set.all()
    print(book)

    注:基于对象的查询,其本质就是多次查询(子查询)

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

    Django还提供了一种直观而搞笑的方式在查询(lookups)种表示关联关系,它能自动确认SQL JOIN联系。要做跨关系查询,就使用两个下划线来连接模型(model)间关联字段的名称,知道最终链接到你想要的model为止。

    一对一查询:

    正向查询(按字段):authordetail
    # 查询Yven的地址
    models.Author.objects.filter(name='Yven').values('authordetail__addr')
    
    
    反向查询(按表名):author
    # 查询Yven的地址
    models.AuthorDetail.objects.filter(author__name='Yven').values('addr')

    一对多查询:

    正向查询(按字段):publish
    # 查询西游记的出版社名
    models.Book.objects.filter(name='西游记').values('publish__name')
    
    
    反向查询(按表名):book
    # 查询西游记的出版社名
    models.Publish.objects.filter(book__name='西游记').values('name')

    多对多查询:

    正向查询(按字段):authors
    # 查询水浒传的作者性别
    models.Book.objects.filter(name='水浒传').values('authors__sex')
    
    
    反向查询(按表名):book
    # 查询水浒传的作者性别
    models.Author.objects.filter(book__name='水浒传').values('sex')
  • 相关阅读:
    Delphi 日期函数的单元 DateUtils
    学习官方示例 SysUtils.DecodeDate、DecodeTime
    msp430的常量可以这样定义
    学习官方示例 SysUtils.EncodeDate、EncodeTime、StrToDate、StrToTime、StrToDateTime
    Delphi中Format与FormatDateTime函数详解
    csdn太慢了搬到园子里来
    .net 2.0 真的能与1.1 安全正确地运行在同一台电脑上吗?
    照着这些做,生活自然很开心
    【转】SQL中取当前记录的ID>SCOPE_IDENTITY()
    [转]Windows XP Service Pack 2中弹出窗口拦截器的研究
  • 原文地址:https://www.cnblogs.com/Mister-JH/p/9954642.html
Copyright © 2011-2022 走看看