Django ORM 数据库常用操作

Python
311
0
0
2023-02-12
标签   Django

设置数据库字段映射:

from django.db import models
import sqlite3

class User(models.Model):
    id = models.AutoField(primary_key=True)    # 设置ID字段(默认自增长)
    username = models.CharField(max_length=32) # 设置用户名最大32个字符
    password = models.CharField(max_length=32) # 设置用户密码
    data = models.DateField()                  # 注册日期
    # 设置最大5位数,其中小数点占用2位
    number = models.DecimalField(max_digits=5,decimal_places=2)

更新与迁移数据库:

python manage.py makemigrations   # 将你的数据库变动记录下来(并不会帮你创建表)
python manage.py migrate          # 将你的数据库变动正在同步到数据库中
python manage.py createsuperuser  # 创建一个超级用户

ORM 数据添加与删除:

from django.shortcuts import render,HttpResponse
from MyWeb import models

def insert(request):
    # ---------------------------------------------------------------------
    # 添加表记录,方式1
    models.User.objects.create(username="admin",password="123123",data="2019-01-01",number=3.1)
    models.User.objects.create(username="guest", password="123456", data="2019-02-12", number=2.1)
    models.User.objects.create(username="admin", password="123123", data="2019-02-12", number=2.1)
    models.User.objects.create(username="wangwu", password="rwqwe33", data="2018-02-12", number=4.1)
    models.User.objects.create(username="zhangsan", password="8888", data="2017-05-21", number=9.9)
    models.User.objects.create(username="lisi", password="99994", data="2010-2-11", number=8.1)

    # 添加表记录,方式2
    dic = {"username":"wangermazi","password":"123321","data":"2019-12-12","number":2.15}
    models.User.objects.create(**dic)

    # 添加表记录,方式3
    obj = models.User(username="lyshark",password="1233",data="2010-01-01",number=3.14)
    obj.save()

    # 添加表记录,方式4
    obj = models.User()
    obj.username="django"
    obj.password="55555"
    obj.data="2003-01-12"
    obj.number="3.14"
    obj.save()

    # ---------------------------------------------------------------------
    # 更新数据的方式
    models.User.objects.filter(id=2).update(username="hello")
    # 第二种更新数据的方式
    obj = models.User.objects.get(id=2)
    obj.username="tomcat"
    obj.password="tomcat"
    obj.save()

    # ---------------------------------------------------------------------
    # 删除数据的方式
    models.User.objects.filter(id=1).delete()    # 删除id是1的一条数据
    models.User.objects.get(id=2).delete()       # 删除id是2的一条数据
    models.User.objects.all().delete()           # 删除所有数据

    return  HttpResponse("<h1>hello lyshark</h1>")

ORM 单表查询操作:

from django.shortcuts import render,HttpResponse
from MyWeb import models

def select(request):
    # 通过ORM模型执行原生SQL语句
    ret = models.CPU.objects.raw('select * from MyWeb_cpu where Times>="{}" and Times <="{}";'.
                                 format("2020-01-02T09:29","2020-01-02T09:30"))
    for item in ret:          # 遍历出内部数据
        print(item.Times)
        print(item.__dict__)

    print(models.User.objects.all())                               # 获取所有数据
    print(models.User.objects.count())                             # 获取数据库中的总共记录数
    print(models.User.objects.filter(username="admin").count())    # 获取admin这条记录的数量

    print(models.User.objects.filter(username="lyshark"))          # 查询username=lyshark的记录
    print(models.User.objects.filter(id=1,username="admin"))       # 查询ID=1且username=admin的记录

    # 查询用户名是lyshark,并且拿到它的id与password字段数据
    print(models.User.objects.filter(username="lyshark").values("id","password"))
    # 查询记录中是lyshark的记录,并且拿到它的id和password,且转换成元组的形式返回
    print(models.User.objects.filter(username="lyshark").values_list("id","password"))

    print(models.User.objects.get(username="lyshark"))                   # 得到model对象
    print(models.User.objects.exclude(username="admin"))                 # 查询所有用户记录,排除掉admin的记录
    print(models.User.objects.filter(username="admin").exclude(id=3))    # 支持链式过滤,查找admin的记录,排除掉id=3

    print(models.User.objects.all().order_by("id"))                # 查询记录并以id字段正向排序
    print(models.User.objects.all().order_by("-id"))               # 同样可以实现反向排序
    print(models.User.objects.all().order_by("id").reverse())      # 查询记录并以id字段反向排序
    print(models.User.objects.filter(username="admin").values("username").distinct()) # 去重

    print(models.User.objects.all().first())                 # 查询第一条记录
    print(models.User.objects.all().last())                  # 查询最后一条记录

    print(models.User.objects.filter(id__lt=5,id__gt=1))     # 查询ID小于5且大于1的数据
    print(models.User.objects.filter(id__in=[1,2,3]))        # 查询ID等于1,2,3的行
    print(models.User.objects.filter(id__range=[1,100]))     # 查询UD在1-100范围内的行

    print(models.User.objects.filter(username__contains="ad").values_list())  # 模糊查询(大小写敏感)
    print(models.User.objects.filter(username__icontains="ad").values_list()) # 模糊查询(大小写不敏感)

    print(models.User.objects.all()[1:3])   # 查询后切片,只取出1-3行元素
    print(models.User.objects.all()[2:9])   # 查询切片,只取出2-9行元素

    return  HttpResponse("<h1>hello lyshark</h1>")

ORM 一对多的使用:: 比如说一个出版社可以出版多本书,但是一本书只能够在一个出版社进行发表,这就是一个典型的一对多的关系,一对多models.ForeignKey(),如下我们首先创建一个Book表,然后创建一个Publish表,一个Publish记录中可以包含多本书.

from django.db import models
import sqlite3

class Book(models.Model):
    id = models.AutoField(primary_key=True)                     # 自增长的一个主键
    title = models.CharField(max_length=32)                     # 书籍名称
    data = models.DateField()                                   # 出版日期
    price = models.DecimalField(max_digits=5,decimal_places=2)  # 一共5位保留两位小数
    # 建立一对多关系,关联到Publish表中,django会自动在publish_key后面加上_id
    publish_key = models.ForeignKey("Publish",on_delete=models.CASCADE)

class Publish(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)     # 出版社名字
    addr = models.CharField(max_length=32)     # 出版社地址
python manage.py makemigrations   # 将你的数据库变动记录下来(并不会帮你创建表)
python manage.py migrate          # 将你的数据库变动正在同步到数据库中

创建一对多关系

from django.shortcuts import render,HttpResponse
from MyWeb import models

def insert(request):
    # 首先创建两个出版社名字
    models.Publish.objects.create(name="人民出版社",addr="中国 北京")
    models.Publish.objects.create(name="清华出版社",addr="北京 海淀")

    # 一对多关系的添加方式:第一种方式
    models.Book.objects.create(title="<Python从入门到入土>",data="2019-12-12",price=22,publish_key_id=1)
    models.Book.objects.create(title="<java 从入门到放弃>", data="2019-11-24", price=55, publish_key_id=1)
    models.Book.objects.create(title="<go 从闰土到入土>", data="2018-11-24", price=77, publish_key_id=1)

    # 一对多关系的添加方式:第二种添加方式(推荐)
    obj = models.Publish.objects.filter(name="清华出版社")[0]
    print("出版社ID号:{}".format(obj.id))
    models.Book.objects.create(title="<简爱>",data="2019-01-01",price=45.5,publish_key_id=obj.id)
    models.Book.objects.create(title="<骆驼祥子>", data="2007-05-01", price=25.5, publish_key_id=obj.id)

    # 一对多关系的添加方式:第三种添加方式
    obj = models.Publish.objects.get(name="人民出版社")
    book = models.Book(title="<django 姜哥>",data="2014-01-02",price=22.6,publish_key_id=obj.id)
    book.save()
    
    return  HttpResponse("<h1>hello lyshark</h1>")

一对多的查询

from django.shortcuts import render,HttpResponse
from MyWeb import models

def insert(request):
    # 普通查询:查询人民出版社出版过的所有书籍
    obj = models.Publish.objects.get(name="人民出版社")
    bookOBJ = obj.book_set.all()
    for item in bookOBJ:
        print("出版书籍:{} 出版日期:{} ".format(item.title,item.data))

    # 正向查询:查询<Python从入门到入土>这本书的出版社的地址
    bookOBJ = models.Book.objects.filter(title="<Python从入门到入土>")[0]
    print("书籍:{}  出版地址是:{}".format(bookOBJ.title,bookOBJ.publish_key.addr))

    # 反向查询: 查询人民出版社出版过的所有的书的价格和名字
    publishOBJ = models.Publish.objects.filter(name="人民出版社")[0]
    book_dic = publishOBJ.book_set.all().values('title','price')[0]
    print("书籍:{}  当前价格:{}".format(book_dic['title'],book_dic['price']))

    # 另一种查询:查询人民出版社出版过的所有书籍,并打印出价格 (高效查询)
    ret = models.Publish.objects.filter(name="人民出版社").values("book__title","book__price")
    for i in range(0,len(ret)):
        print("出版书籍: {}  当前价格:{} ".format(ret[i]['book__title'],ret[i]['book__price']))

    # 第二种查询方式(该方法更简单)
    ret = models.Publish.objects.filter(name="人民出版社").values("book__title","book__price")
    for i in ret:
        print("出版书籍: {}  当前价格:{} ".format(i['book__title'], i['book__price']))

    return  HttpResponse("<h1>hello lyshark</h1>")

ORM 多对多的使用:: 一个作者可以写多本书,同样的一本书可能是由多个作者一起写出来的,这就是多对多的关系,多对多models.ManyToManyField()

from django.db import models
import sqlite3

class Book(models.Model):
    id = models.AutoField(primary_key=True)                     # 自增长的一个主键
    title = models.CharField(max_length=32)                     # 书籍名称
    data = models.DateField()                                   # 出版日期
    price = models.DecimalField(max_digits=5,decimal_places=2)  # 一共5位保留两位小数
    # 建立一对多关系,关联到Publish表中,django会自动在publish_key后面加上_id
    publish_key = models.ForeignKey("Publish",on_delete=models.CASCADE)

    # 多对多,django会自动创建一个新的表book_author用来记录多对多键值对
    author = models.ManyToManyField("Author")

class Publish(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)     # 出版社名字
    addr = models.CharField(max_length=32)     # 出版社地址

class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)     # 作者姓名
    age = models.IntegerField()                # 作者年龄

多对多的数据创建操作技巧

from django.shortcuts import render,HttpResponse
from MyWeb import models

def insert(request):
    # 我们来创建几个书籍作者
    models.Author.objects.create(name="张三", age=22)
    models.Author.objects.create(name="李四", age=33)
    models.Author.objects.create(name="王五", age=67)
    models.Author.objects.create(name="老王", age=87)
    models.Author.objects.create(name="小张", age=43)

    # -----------------------------------------------------------------------------
    # 拿到一个出版社的对象,我们这本《鲁迅散文》是清华出版社的
    PublishOBJ = models.Publish.objects.filter(name="清华出版社")[0]
    # 接着我们创建一本书,并关联一对多的关系(清华出版社->鲁迅散文)
    BookObj = models.Book.objects.create(title="<鲁迅散文>",data="2019-01-23",price=34.5,publish_key=PublishOBJ)
    # 接着我们取出本书的作者:比如本书是由张三,李四,老王写出来的.
    zhangsan = models.Author.objects.filter(name="张三")[0]
    lisi = models.Author.objects.filter(name="李四")[0]
    laowang = models.Author.objects.filter(name="老王")[0]
    # 最后我们将这本<鲁迅散文>与这三个作者关联起来
    BookObj.author.add(zhangsan,lisi,laowang)

多对多的查询

from django.shortcuts import render,HttpResponse
from MyWeb import models

def insert(request):
    # 正向查询:查询<鲁迅散文>这本书是由那几个人写的,并打印出他的年龄
    BookOBJ = models.Book.objects.filter(title="<鲁迅散文>")[0]
    name = BookOBJ.author.all().values("name")
    age = BookOBJ.author.all().values("age")
    for i in range(0,len(name)):
        print("书籍作者: {}".format(name[i]['name']))

    # 反向查询:查询李四这个作者写过那几本书
    lisi = models.Author.objects.filter(name="李四")[0]
    print("该作者写过: "+ lisi.book_set.all().first().title)

    # 查询人民出版社出版过的所有书籍
    publish = models.Publish.objects.get(name="人民出版社")
    booklist = publish.book_set.all()
    for i in range(0,len(booklist)):
        print("查询到人民出版社,出版过: {}".format(booklist[i].title))

    # 另外一种查询方式:查询张三这个人写过的书
    ret = models.Author.objects.filter(name="张三").values("book__title")
    print(ret)

    return HttpResponse("hello lyshark")

ORM 聚合查询与分组查询:

from django.db.models import Avg,Sum,Count,Max,Min

def insert(request):
    # 查询所有图书的平均价格
    print(models.Book.objects.all().aggregate(Avg("price")))
    # 另一种自定义命名查询
    print(models.Book.objects.all().aggregate(avg = Avg("price")))
    # 如果你希望生成不止一个聚合,可以这样写
    print(models.Book.objects.all().aggregate(avg=Avg("price"),max=Max("price"),min=Min("price")))

    # 查询出,每本书的作者的总个数
    #print(models.Book.objects.all().annotate(num=Count("author__name")).values("num"))
    bookOBJ = models.Book.objects.all().annotate(num=Count("author__name"))
    for item in bookOBJ:
        print("书籍:{}  作者数量:{}".format(item.title,item.num))

    # 统计出每个出版社出版过最便宜的书的价格(方式1)
    print(models.Publish.objects.all().annotate(MinBook=Min("book__price")).values("name","MinBook"))

    # 统计出每个出版社出版过最贵的书的价格(方式2)
    publishOBJ = models.Publish.objects.annotate(MaxBook=Max("book__price"))
    for item in publishOBJ:
        print("出版社:{}  最贵的书:{}".format(item.name,item.MaxBook))

    # 统计出书籍名称以<鲁迅开头的书籍,是由几个作者写的
    print(models.Book.objects.filter(title__startswith="<鲁迅").annotate(Num=Count("author__name")).values("Num"))
    bookOBJ = models.Book.objects.filter(title__startswith="<鲁迅").annotate(Num=Count("author__name"))
    for item in bookOBJ:
        print("书籍:{}  由{}个作者共同完成".format(item.title,item.Num))

    # 统计不止两个作者的图书,并打印出图书的名字
    print(models.Book.objects.annotate(num=Count("author__name")).filter(num__gt=2).values("title","num"))

    # 根据一本图书作者数量的多少对查询集QuerySet进行排序
    print(models.Book.objects.all().annotate(num=Count("author__name")).order_by("num"))

    # 查询每个作者出过的书的总价格,每个作者出过书之和
    print(models.Author.objects.all().annotate(PriceSum=Sum("book__price")).values("name","PriceSum"))

    return HttpResponse("hello lyshark")

ORM Django之F查询与Q查询:

from django.db.models import F,Q

def select(request):
    # ---------------------------------------------------------------
    # F查询:专门针对对象中某列中的某个值进行操作

    # 需求:通过F查询我们将book表中所有图书的价格全部涨价20元
    # F查询:作用是取出 price 字段的值,然后进行 +20 的操作
    models.Book.objects.all().update(price=F("price") + 20)
    # 查询评论数大于收藏数2倍的书籍
    models.Book.objects.filter(commnetNum__lt=F('keepNum') * 2)
    # 查看评论数大于阅读数的书
    print(models.Book.objects.filter(commentNum__gt=F("readNum")))

    # ---------------------------------------------------------------
    # Q查询: 用于应对更加复杂的查询需求,例如使用and或or进行的复杂查询.

    # Q查询(单条件查询): 查询book表中,id=1的书,并打印出它的title字段.
    print(models.Book.objects.filter(Q(id=1)).values("title"))
    # Q查询(多条件查询):查询book表中,id=1并且title=<Python从入门到入土> 查到后打印出price价格.
    print(models.Book.objects.filter(Q(id=1) & Q(title="<Python从入门到入土>")).values("price"))

    # Q查询(跨表查询):查询author__name=张三的人写过的书,并打印出title
    print(models.Book.objects.filter(Q(author__name="张三")).values("title"))