Django之模型层&ORM操作

一. 单表查询:

 1.在模型层创建模型表:

from django.db import models

# Create your models here.
# 单表查询表
class User(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    register_time = models.DateField()

     2.连接MySQL,创建表 (具体操作见https://www.cnblogs.com/sima-3/p/10987276.html)

       3.在test.py中进行单表查询测试, 首先配置环境:

from django.test import TestCase

# Create your tests here.
import os

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day58.settings")
    import django
    django.setup()
    from app01 import models

a.新增数据:

方式一:对象的create方法添加记录

user_obj=models.User.objects.create(name=‘jason‘,age=‘18‘,register_time=‘2019-6-12‘)
print(user_obj.name)

方式二:对象的save方法添加记录

from datetime import datetime
ctime=datetime.now()
user_obj=models.User(name=‘egon‘,age=‘18‘,register_time=ctime)
user_obj.save()
print(user_obj.register_time)

b.修改数据:

方式一:数据对象更新记录

user_obj=models.User.objects.filter(name=‘jason‘).last()
user_obj.name=‘kevin‘
user_obj.age=‘18‘
user_obj.save()

方式二:queryset对象的update方法更新记录

user_list=models.User.objects.filter(pk=6)
user_list.update(name=‘tank‘)

c.删除数据:

方式一:数据对象删除记录

user_obj=models.User.objects.filter(name=‘jason‘)[0]
user_obj.delete()

 方式二:queryset对象删除记录

user_list=models.User.objects.filter(age=‘18‘)
user_list.delete()

d.查询数据:

     # < 1 > all(): 查询所有结果

    # < 2 > filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
    # res = models.User.objects.filter(name=‘jason‘,age=17)
    # filter内可以放多个限制条件但是需要注意的是多个条件之间是and关系
    # print(res)

    # < 3 > get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。                          (源码就去搂一眼~诠释为何只能是一个对象)
                            # 不推荐使用

    # < 4 > exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
    # res = models.User.objects.exclude(name=‘jason‘)
    # print(res)
    # < 5 > order_by(*field): 对查询结果排序(‘-id‘) / (‘price‘)
    # res = models.User.objects.order_by(‘age‘)   # 默认是升序
    # res = models.User.objects.order_by(‘-age‘)  # 可以在排序的字段前面加一个减号就是降序
    # res = models.User.objects.order_by(‘name‘)
    # res = models.User.objects.order_by(‘-name‘)
    # print(res)

    # < 6 > reverse(): 对查询结果反向排序 >> > 前面要先有排序才能反向
    # res = models.User.objects.order_by(‘age‘).reverse()
    # print(res)

    # < 7 > count(): 返回数据库中匹配查询(QuerySet) 的对象数量。
    # res = models.User.objects.count()
    # res = models.User.objects.all().count()
    # print(res)

    # < 8 > first(): 返回第一条记录
    # res = models.User.objects.all().first()
    # res = models.User.objects.all()[0]  # 不支持负数的索引取值
    # print(res)

    # < 9 > last(): 返回最后一条记录
    # res = models.User.objects.all().last()
    # print(res)

    # < 10 > exists(): 如果QuerySet包含数据,就返回True,否则返回False
    # res = models.User.objects.all().exists()
    # res1 = models.User.objects.filter(name=‘jason‘,age=3).exists()
    # print(res,res1)

    # < 11 > values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
                             model的实例化对象,而是一个可迭代的字典序列
    # res = models.User.objects.values(‘name‘)  # 列表套字典
    # res = models.User.objects.values(‘name‘,‘age‘)  # 列表套字典
    # print(res)

    # < 12 > values_list(*field): 它与values()
                                  非常相似,它返回的是一个元组序列,values返回的是一个字典序列
    # res = models.User.objects.values_list(‘name‘,‘age‘)  # 列表套元祖
    # print(res)

    # < 13 > distinct(): 从返回结果中剔除重复纪录  去重的对象必须是完全相同的数据才能去重
    # res = models.User.objects.values(‘name‘,‘age‘).distinct()
    # print(res)

e.神奇的双下划线查询 (基于queryset对象操作):

  查询年轻大于44岁的用户
    # res = models.User.objects.filter(age__gt=44)
    # print(res)

  查询年轻小于44岁的用户
    # res = models.User.objects.filter(age__lt=44)
    # print(res)

  查询年轻大于等于44岁的用户
    # res = models.User.objects.filter(age__gte=44)
    # print(res)

 查询年轻小于等于44岁的用户
    # res = models.User.objects.filter(age__lte=44)
    # print(res)

 查询年龄是44或者22或者73的用户
    # res = models.User.objects.filter(age__in=[44,22,73])
    # print(res)

 查询年龄在22到44范围内
    # res = models.User.objects.filter(age__range=[22,44])
    # print(res)

 查询年份
    # res = models.Book.objects.filter(publish_date__year=2019)
    # print(res)

 查询名字中包含字母n的用户  sqlite数据库演示不出来大小写的情况!!!
    # res = models.Author.objects.filter(name__contains=‘n‘)
    区分大小写
    # res = models.Author.objects.filter(name__icontains=‘n‘)
    不分大小写
  # print(res)

 查询名字以j开头的用户
    # res = models.User.objects.filter(name__startswith=‘j‘)
    # print(res)

查询名字以n结尾的用户
    # res = models.User.objects.filter(name__endswith=‘n‘)
    # print(res)

二.多表查询:

 1.在模型层创建模型表:

# 多表查询表
class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish_date = models.DateField(auto_now_add=True)
    # 外键关系
    publish = models.ForeignKey(to=‘Publish‘)
    authors = models.ManyToManyField(to=‘Author‘)  # 虚拟字段, 信号字段

    def __str__(self):
        return ‘书籍对象的名字:%s‘%self.title

class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)
    email = models.EmailField()  # 对应就是varchar类型

    def __str__(self):
        return ‘出版社对象的名字:%s‘%self.name

class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    authordetail = models.OneToOneField(to=‘AuthorDetail‘)

    def __str__(self):
        return  ‘作者对象的名字:%s‘%self.name

class AuthorDetail(models.Model):
    phone = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)

五张表如下图所示(多对多会新增一张表):

先在author, authordetail, publish三张表中填写记录,book, book_author两张表暂不填:

其各表关系如下:

book ---------  publish            一对多关系

book ---------  author             多对多关系  ------- 产生 book_author

author--------- authordetail    一对一关系

publish 表记录:

author  表记录:

authordetail 表记录:

    2.一对多字段的增删改查:

            a.在book表中添加记录:

        

# 方式一:数据对象的create方法添加记录
book_obj=models.Book.objects.create(title=‘孙子兵法‘,price=‘66.88‘,publish_id=3)
print(book_obj.title)

# 方式二:数据对象的save方法添加记录
book_obj=models.Book(title=‘三国志‘,price=‘33.66‘,publish_id=4)
book_obj.save()
print(book_obj.title)

#除了用publish_id关联book表,还可传publish对象publish_obj,因为book表中有publish字段
publish_obj=models.Publish.objects.filter(pk=4).first()book_obj=models.Book.objects.create(title=‘洛神赋‘,price=‘98.89‘,publish=publish_obj)

添加记录后:

           b.在book表中修改记录:

# 方式一:数据对象更新记录

book_obj=models.Book.objects.filter(pk=4).first()
book_obj.title=‘厚黑学‘
book_obj.publish_id=2
book_obj.save()
print(book_obj.title)

# 方式二:queryset对象的update方法更新记录

book_list=models.Book.objects.filter(pk=6)
publish_obj=models.Publish.objects.filter(pk=4).first()
book_list.update(title=‘红楼梦‘,publish=publish_obj)
print(book_list)

修改记录后:

      c.在book表中删除记录:

# 方式一:数据对象删除记录
book_obj=models.Book.objects.filter(pk=4)[0]
book_obj.delete()

 # 方式二:queryset对象的update方法删除记录
book_list=models.Book.objects.filter(pk=6)book_list.delete()
如果删除出版社,相应的书也会被删除(级联删除)

删除记录后:

    2.多对多字段的增删改查:

        a.在book_authors表中添加记录:

          给书籍绑定与作者之间的关系:

    # 添加关系 add支持传数字或对象,并且都可以传多个
    # 方式一:直接添加authors_id
    book_obj = models.Book.objects.filter(pk=3).first()
    book_obj.authors.add(4)
    book_obj.authors.add(2,3)

    # 方式二: 添加authors对象
    author_obj = models.Author.objects.filter(pk=2).first()
    author_obj1 = models.Author.objects.filter(pk=3).first()
    book_obj = models.Book.objects.filter(pk=5).first()
    book_obj.authors.add(author_obj,author_obj1)

        绑定之后:

     b.在book_authors表中更新记录:

    修改书籍与作者的关系  set()  set传的必须是可迭代对象!!!
    book_obj = models.Book.objects.filter(pk=3).first()
    # 可以传数字和对象,并且支持传多个
    book_obj.authors.set((2,))
    # book_obj.authors.set((1,2,3))

    author_list = models.Author.objects.all()     #[{},{},...],包含所有的作者对象,主键id=2,3,4,5
    book_obj = models.Book.objects.filter(pk=5).first()
    book_obj.authors.set(author_list)

       修改之后:

         

   c.在book_authors表中删除记录:

         删除书籍与作者的绑定关系: 需要将queryset打散:

    book_obj = models.Book.objects.filter(pk=3).first()
    book_obj.authors.remove(2)
    # book_obj.authors.remove(4,3)

    # author_obj = models.Author.objects.all().first()
    # book_obj.authors.remove(author_obj)
    book_obj = models.Book.objects.filter(pk=5).first()
    author_list = models.Author.objects.all()
    book_obj.authors.remove(*author_list)

      正好将所有记录都删完了 !!!

   补充: 清空  clear()  清空的是当前这个表记录中id为3的book对应的所有绑定关系
# book_obj = models.Book.objects.filter(pk=3).first()
    # book_obj.authors.clear()

三.正向反向概念

# 正向与方向的概念解释

# 一对一
# 正向:author---关联字段在author表里--->authordetail        按字段
# 反向:authordetail---关联字段在author表里--->author        按表名小写
    # 查询jason作者的手机号   正向查询
    # 查询地址是 :山东 的作者名字   反向查询

# 一对多
# 正向:book---关联字段在book表里--->publish        按字段
# 反向:publish---关联字段在book表里--->book        按表名小写_set.all() 因为一个出版社对应着多个图书

# 多对多
# 正向:book---关联字段在book表里--->author        按字段
# 反向:author---关联字段在book表里--->book        按表名小写_set.all() 因为一个作者对应着多个图书

# 连续跨表
    # 查询图书是三国演义的作者的手机号,先查书,再正向查到作者,在正向查手机号

# 总结:基于对象的查询都是子查询,这里可以用django配置文件自动打印sql语句的配置做演示

1.基于对象的表查询
      a. 正向:

# 一对多
# 查询书籍是三国志的出版社邮箱
book_obj = models.Book.objects.filter(title=‘三国志‘).first()
print(book_obj.publish.email)

# 多对多
# 查询书籍是山海经的作者的姓名
book_obj = models.Book.objects.filter(title=‘山海经‘).first()
print(book_obj.authors)  # app01.Author.None,多对多必须用all查询
print(book_obj.authors.all())  # <QuerySet [<Author: 作者对象的名字:jason>]>

# 一对一
# 查询作者为jason电话号码
user_obj = models.Author.objects.filter(name=‘jason‘).first()
print(user_obj.authordetail.phone)

      b.反向:

    # 一对多字段的反向查询
    # 查询出版社是江苏日报出版社出版的书籍
    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: 书籍对象的名字:洛神赋>]>

    # 多对多字段的反向查询
    # 查询作者jason写过的所有的书
    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: 书籍对象的名字:三国志 >] >

    # 一对一字段的反向查询,一对一不用加_set,直接可跨表拿到name字段的值
    # 查询作者电话号码是456的作者姓名
    authordetail_obj = models.AuthorDetail.objects.filter(phone=456).first()
    print(authordetail_obj.author.name)

2.基于双下滑线的查询:

      a.正向:

    # 查询书籍为洛神赋的出版社地址
    res = models.Book.objects.filter(title=‘洛神赋‘).values(‘publish__addr‘,‘title‘)
    print(res)
    # < QuerySet[{‘publish__addr‘: ‘江苏‘, ‘title‘: ‘洛神赋‘}] >
       # 查询书籍为山海经的作者的姓名
    res = models.Book.objects.filter(title=‘山海经‘).values("authors__name",‘title‘)
    print(res)
    # < QuerySet[{‘authors__name‘: ‘jason‘, ‘title‘: ‘山海经‘}] >
       # 查询作者为jason的家乡
    res = models.Author.objects.filter(name=‘jason‘).values(‘authordetail__addr‘)
    print(res)
    # < QuerySet[{‘authordetail__addr‘: ‘东京‘}] >

      b.反向:

    # 查询人民日报出版社出版的书名
    res = models.Publish.objects.filter(name=‘人民日报‘).values(‘book__title‘)
    print(res)
    # < QuerySet[{‘book__title‘: ‘山海经‘}] >

    # 查询电话号码为789的作者姓名
    res = models.AuthorDetail.objects.filter(phone=789).values(‘author__name‘)
    print(res)
    # < QuerySet[{‘author__name‘: ‘tank‘}] >

    # 查询作者为jason的写的书的名字
    res = models.Author.objects.filter(name=‘jason‘).values(‘book__title‘)
    print(res)
    # < QuerySet[{‘book__title‘: ‘山海经‘}, {‘book__title‘: ‘三国志‘}] >

     c.跨三张表查询:

    # 查询书籍为三国志的作者的电话号码
    res = models.Book.objects.filter(title=‘三国志‘).values(‘authors__authordetail__phone‘)
    print(res)
    # < QuerySet[{‘authors__authordetail__phone‘: ‘123‘}] >

    d.同一问题不同角度查询:

    # 查询jason作者的手机号
    # 正向
    res = models.Author.objects.filter(name=‘jason‘).values(‘authordetail__phone‘)
    print(res)
    # < QuerySet[{‘authordetail__phone‘: ‘123‘}] >
    # 反向
    res = models.AuthorDetail.objects.filter(author__name=‘jason‘).values(‘phone‘)
    print(res)
    # < QuerySet[{‘phone‘: ‘123‘}] >
    # 查询出版社为新华日报出版社的所有图书的名字和价格
    # 正向
    res = models.Publish.objects.filter(name=‘新华日报‘).values(‘book__title‘,‘book__price‘)
    print(res)
    # < QuerySet[{‘book__title‘: ‘战国策‘, ‘book__price‘: Decimal(‘86.66‘)}] >
    # 反向
    res = models.Book.objects.filter(publish__name=‘新华日报‘).values(‘title‘,‘price‘)
    print(res)
    # < QuerySet[{‘title‘: ‘战国策‘, ‘price‘: Decimal(‘86.66‘)}] >
    # 查询人民日报出版社出版的价格大于10的书
    # 正向
    res = models.Publish.objects.filter(name="人民日报",book__price__gt=10).values(‘book__title‘,‘book__price‘)
    print(res)
    # < QuerySet[{‘book__title‘: ‘山海经‘, ‘book__price‘: Decimal(‘18.88‘)}] >
    # 反向
    res = models.Book.objects.filter(price__gt=10,publish__name=‘人民日报‘).values(‘title‘,‘price‘)
    print(res)
    # < QuerySet[{‘title‘: ‘山海经‘, ‘price‘: Decimal(‘18.88‘)}] >

四.聚合查询  aggregate

 from django.db.models import Max,Min,Count,Sum,Avg
    # 查询所有书籍的作者个数
    res = models.Book.objects.aggregate(count_num=Count(‘authors‘))
    print(res)
    # {‘count_num‘: 3}
    # 查询所有出版社出版的书的平均价格
    res = models.Publish.objects.aggregate(avg_price=Avg(‘book__price‘))
    print(res)  # {‘avg_price‘: 59.5225}
    # 统计江苏日报出版社出版的书籍的个数
    res = models.Publish.objects.filter(name=‘江苏日报‘).aggregate(count_num=Count(‘book__id‘))
    print(res)
    # {‘count_num‘: 2}

五.分组查询 (group_by)   annotate

  # 统计每个出版社出版的书的平均价格
    res = models.Publish.objects.annotate(avg_price=Avg(‘book__price‘)).values(‘name‘,‘avg_price‘)
    print(res)
    # < QuerySet[{‘name‘: ‘人民日报‘, ‘avg_price‘: 18.88}, {‘name‘: ‘新华日报‘, ‘avg_price‘: 86.66},
    # {‘name‘: ‘江苏日报‘, ‘avg_price‘: 66.275}, {‘name‘: ‘上海日报‘, ‘avg_price‘: None}] >

  # 统计每一本书的作者个数
    res = models.Book.objects.annotate(count_num=Count(‘authors‘)).values(‘title‘,‘count_num‘)
    print(res)
    # < QuerySet[{‘title‘: ‘山海经‘, ‘count_num‘: 1}, {‘title‘: ‘战国策‘, ‘count_num‘: 0},
    # {‘title‘: ‘三国志‘, ‘count_num‘: 1}, {‘title‘: ‘洛神赋‘, ‘count_num‘: 1}] >

 # 统计出每个出版社卖的最便宜的书的价格
    res = models.Publish.objects.annotate(min_price=Min(‘book__price‘)).values(‘name‘,‘min_price‘)
    print(res)

  # 查询每个作者出的书的总价格
    res = models.Author.objects.annotate(sum_price=Sum(‘book__price‘)).values(‘name‘,‘sum_price‘)
    print(res)
# <QuerySet [{‘name‘: ‘jason‘, ‘sum_price‘: Decimal(‘52.54‘)}, {‘name‘: ‘kevin‘, ‘sum_price‘: Decimal(‘98.89‘)},
# {‘name‘: ‘egon‘, ‘sum_price‘: None}, {‘name‘: ‘tank‘, ‘sum_price‘: None}]>

    

       

原文地址:https://www.cnblogs.com/sima-3/p/11013499.html

时间: 2024-10-31 21:30:06

Django之模型层&ORM操作的相关文章

Django之模型层第二篇:多表操作

Django之模型层第二篇:多表操作 一 表关系回顾 ? 在讲解MySQL时,我们提到,把应用程序的所有数据都放在一张表里是极不合理的. ? 比如我们开发一个员工管理系统,在数据库里只创建一张员工信息表,该表有四个字段:工号.姓名.部门名.部门职能描述,此时若公司有1万名员工,但只有3个部门,因为每一名员工后都需要跟着部门信息(部门名.部门职能),所以将会导致部门信息出现大量重复.浪费空间. ? 解决方法就是将数据存放于不同的表中,然后基于foreign key建立表之间的关联关系. ? 细说的

Django框架-模型层

Django框架-模型层 一.单表查询之必知必会13条 1.时间字段中的两个关键性参数 create_time = models.DateField() # 年月日 create_time = models.DateTimeField() # 年月日时分秒 # 两个关键性参数 # auto_now:每次操作数据 都会自动刷新当前操作的时间 # auto_now_add:在创建数据的时候 会自动将创建时间记录下来 后续的修改不会影响该字段 2.搭建测试环境 在django中,你可以写一个单独测试某

Django的模型层

Django模型层是Django框架自己定义的一套独特的ORM技术.使用django模型开发的首要任务就是定义模型类及其属性.每个模型类都可以被映射为数据库中的一个数据表,而类属性被映射数据字段,除此之外,数据库表的主键.外键.约束等也通过类属性完成定义. 1.模型定义,通过模型类中的Mata子类定义数据模型,比如数据库的表名.数据默认排序方式等. 2.普通字段类型,普通字段类型指模型类中除了外键关系外的数据字段属性. 3.常用字段参数,每个字段类型都有一些特定的HTML标签和表单验证参数, 4

django之模型层(待补充)

模型层 1. ORM查询 所有代码都是在test.py文件中运行的 注意:我如果想在test.py文件中测试相关代码,那么必须要进行配置,不然会报以下的错误 django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable D

Django入门 &#160; 数据库的ORM操作之一对多

Django对数据库的是通过ORM实现.什么叫做ORM呢?简单来说,我们通过sql语句查询一张表的所有数据的语句如下  select * from test.而Django中用到的表都是在models.py文件里定义.所以我们要查查询test表里的数据可以通过 test_obj = models.test.objects.all()来获取test表里所有数据的对象.再通过 test_obj.values()方法将每一行数据的里的各个字段以key和value的字典形式读取出来.这就叫ORM操作.

9.17 模型层 ORM 单表操作

1 创建模型 创建名为book的app,在book下的models.py中创建模型: from django.db import models # Create your models here. class Book(models.Model): id=models.AutoField(primary_key=True) title=models.CharField(max_length=32) state=models.BooleanField() pub_date=models.DateF

Django之模型层-多表操作

多表操作 数据库表关系 一对多:两个表之间的关系一旦确定为一对多,必须在数据多的表中创建关联字段 多对多:两个表之间的关系一定确定为多对多,必须创建第三张表(关联表) 一对一:一旦两个表之间的关系确定为一对一,在两种表中任意一张表中建立关联字段unique ORM生成关联表模型 class Book(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=32) pric

Django之模型层(ORM相关知识)

一.ORM对数据库的增改删查 1.单表操作 基于Django自带的sqlite库建立一个User表,表里字段分别有id字段.name字段.age字段.register_time字段 1.1.新增数据 # 基于create创建 user_obj =models.User.objects.create(name='tank',age=73,register_time='2019-2-14') print(user_obj.register_time) # 基于对象的绑定方法创建 user_obj =

django之模型层

1. ORM MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动 ORM是"对象-关系-映射"的简称. Mysql #sql中的表 #创建表: CREATE TABLE employee( id INT PRIMARY KEY auto_increment , name VARCHAR (20), gen