Django ORM 数据库常用操作

时间:2022-05-04 04:36:56

Django是一个开放源代码的Web应用框架,由Python写成。采用了MTV的框架模式,即模型M,视图V和模版T。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。并于2005年7月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的。 -- 百度百科

设置数据库字段映射

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):
    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查询