【Django】ORM增删改查、F对象和Q对象、聚合操作和原生数据库操作

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

1、ORM的增删改查均需要通过管理器对象进行。
2、可使用python3 manage.py shell 进入脚本页方便操作。
3、可修改输出格式在这里插入图片描述

一、ORM查询操作

1、查询方法

在这里插入图片描述

1all()方法

  • 用法MyModel.objects.all()
  • 作用查询所有数据等同于select * from table
  • 返回值QuerySet容器对象内部存放MyModel实例
from bookstore.models import book
books = Book.objects.all()
for book in books:
    print(book.title)

2values(‘列1’,‘列2’)

  • 用法MyModel.objects.values(...)
  • 作用查询部分列的数据并返回等同于select 列1,列2 from xxx
  • 返回值查询结果的容器容器内存字典每个字典代表一条数据格式为{‘列1’:值1,…}
a2 = Book.objects.values('title','pub')
# a2
'''<QuerySet [{'title': 'Python', 'pub': '清华大学出版社'}, {'title': 'Django', 'pub': '清华大学出版社'}, {'title': 'Jquery', 'pub': '清华大学出版社'}, {'title': 'Linux', 'pub': '机械工业出版社'}, {'title': 'HTML5', 'pub': '机械工业出 版社'}]>'''

for book in a2:
     print(book['title'])

3values_list(‘列1’,‘列2’)

  • 用法MyModel.objects.values_list(...)
  • 作用查询部分列的数据并返回等同于select 列1,列2 from xxx
  • 返回值查询结果的容器容器内存元组每个元组代表一条数据格式为(‘值1’,值2),…

4order_by(‘列’)

  1. 用法MyModel.objects.order_by('-列','列')
  2. 作用对查询结果进行根据某个字段选择性排序与sql中的ORDERBY相同
  3. 说明默认是升序降序需加’-’
Book.objects.order_by('-price')
'''<QuerySet [<Book: Jquery_清华大学出版社_90.00__85.00>, <Book: HTML5_机械工业出版社_90.00__105.00>, <Book: Linux_机械工业出版社_80.00__65.00>, <Book: Django_清华大学出版社_75.00__70.00>, <Book: Python_清华大学出版社_20.00__25.00>]>'''
Book.objects.values('title').order_by('-price')
''' <QuerySet [{'title': 'Jquery'}, {'title': 'HTML5'}, {'title': 'Linux'}, {'title': 'Django'}, {'title': 'Python'}]>'''
# QuerySet会自动根据mysql的语序执行
Book.objects.order_by('-price').values('title')
''' <QuerySet [{'title': 'Jquery'}, {'title': 'HTML5'}, {'title': 'Linux'}, {'title': 'Django'}, {'title': 'Python'}]>'''
# 可查询到根据何sql语句得到的对象
print(a5.query)
# SELECT `book`.`title` FROM `book` ORDER BY `book`.`price` DESC

小练习在/bookstore/all_book/路由下用表格展示所有图书的内容

  • 主路由给应用分发路由path('bookstore/',include('bookstore.urls'))
  • bookstore应用下配置目标路由path('all_book/',views.allbook_view)
  • 编写视图函数
from django.http import HttpResponse
from django.shortcuts import render
from .models import Book
# Create your views here.
def allbook_view(request):
    all_book = Book.objects.all().order_by('price')
    return render(request,'bookstore/all_book.html',locals())
  • bookstore应用下创建templates/bookstore文件夹并创建all_book的html页面
<table border="1px" width="800px" height="100px">
      <tr>
           <th>id</th>
           <th>title</th>
           <th>pub</th>
           <th>info</th>
           <th>price</th>
           <th>market_price</th>
           <th>op</th>
       </tr>
       
       {% for book in all_book %}
       <tr>
           <td>{{ book.id }}</td>
           <td>{{ book.title }}</td>
           <td>{{ book.pub }}</td>
           <td>{{ book.info }}</td>
           <td>{{ book.price }}</td>
           <td>{{ book.market_price }}</td>
           <td>
               <a href="">更新</a>
               <a href="">删除</a>
           </td>
       </tr>
       {% endfor %}
</table>

5filter(条件)

  • 语法MyModel.objects.filter(属性1=值1,属性2=值2)
  • 作用返回包含此条件的全部数据集
  • 返回值QuerySet容器对象内部存放MyModel实例
  • 说明多个属性的关系为“与”
from bookstore.models import Book
books = Book.objects.filter(pub='清华大学出版社')
for book in books:
	print(book.title)

6exclude(条件)

  • 语法MyModel.objects.exclude(属性1=值1,属性2=值2)
  • 作用返回不包含此条件的全部数据集
  • 返回值QuerySet容器对象内部存放MyModel实例
  • 说明多个属性的关系为“与”
from bookstore.models import Book
books = Book.objects.exclude(pub='清华大学出版社',price=50)
for book in books:
	print(book.title)

7get(条件)

  • 语法MyModel.objects.get(属性1=值1,属性2=值2)
  • 作用返回满足条件的唯一一条数据
  • 说明只能返回一条数据0或多均报错
from bookstore.models import Book
book = Book.objects.get(pub='清华大学出版社',price=50)
print(book.title)

8类名_查询谓词

  • 定义更灵活的条件查询
  • 说明每一个查询谓词是一个独立的查询功能
查询谓词解释
__exact等值匹配
__contains包含指定值
__startswith以xxx开始
__endswith以xxx结束
__gt大于指定值
__gte大于等于
__lt小于指定值
__lte小于等于
__in是否在指定范围内(列表)
__range是否在指定区间内(元组)

2、更新操作

1更新单个数据

  • 查通过get()得到要修改的实体对象
  • 改通过 对象.属性 的方式修改数据
  • 保存对象.save()保存数据

2批量数据更新

  • 直接调用QuertSet的update(属性=值)实现批量修改
books = Book.object.filter(id__gt=3)
books.update(price=0)

小练习在all_book路由基础上增加更改功能

在/bookstore/update_book/1页面修改书籍的价格.

  1. 编写视图函数
def update_book(request,book_id):
    try:
        book = Book.objects.get(id = book_id)
    except Exception as e:
        print('---update book error is',e)
        return HttpResponse('alter("The book is not existed")')

    if request.method == 'GET':
        return render(request,'bookstore/update_book.html',locals())
    elif request.method == 'POST':
        pass
  1. 配置路由与a标签
path('update_book/<int:book_id>',views.update_book)
<a href="/bookstore/update_book/{{ book.id }}">更新</a>
  1. 编写html页面
<form action='/bookstore/update_book/{{ book.id }}' method='post'>
    title 
    <input type='text' value="{{ book.title }}" readonly>
    <br>
    pub 
    <input type='text' value="{{ book.pub }}" readonly>
    <br>
    info 
    <input type='text' value="{{ book.info }}" readonly>
    <br>
    price 
    <input type='text' name="price" value="{{ book.price }}">
    <br>
    market_price 
    <input type='text' name="market_price" value="{{ book.market_price }}" >
    <br>
    <input type="submit" value='确认修改'>
</form>
  1. 完善视图函数post部分
elif request.method == 'POST':
    price = request.POST['price']
    market_price = request.POST['market_price']
    book.price= price
    book.market_price= market_price
    book.save()
    return HttpResponseRedirect('/bookstore/all_book')

3、删除操作

1单个数据删除

  1. 查找查询结果对应的数据对象
  2. 调用delete()方法实现删除
auth = Author.objects.get(id=1)
auth.delete()

2批量数据删除

  1. 查找查询结果满足条件的所有数据对象
  2. 调用集合对象的delete()方法实现删除
auth = Author.objects.filter(age__gt=65)
auth.delete()

一般都会做“伪删除”即is_active字段为False

小练习增加伪删除书籍的功能

路由/bookstore/delete_book?book_id=xxx相关查询获取数据的地方要过滤出活跃数据。

  1. 配置路由与a标签
path('delete_book',views.delete_book)
<a href="/bookstore/delete_book?book_id={{book.id}}">删除</a>
  1. 编写视图函数
def delete_book(request):
    # 通过查询字符串获取book_id
    book_id = request.GET.get('book_id')
    if not book_id:
        return HttpResponse("The book is not existed")
    try:
        book = Book.objects.get(id = book_id,is_active=True)
    except Exception as e:
        print('---delete book error is',e)
        return HttpResponse("The book is not existed")
    book.is_active = False
    book.save()
    return HttpResponseRedirect('/bookstore/all_book')

二、F对象和Q对象

1、F对象

  • F对象代表数据库中某条记录的字段信息
  • 作用在不获取的情况下对数据库中的字段操作。
from django.db.models import F
F('列名')
Book.objects.all().update(market_price=F('market_price')+10)
Book.objects.filter(market_price__gt=F('price'))

注比起读取再修改F对象相当于上了一把锁多人操作也不会造成竞争。

2、Q对象

Q对象可以操作复杂的逻辑(与&或|非~操作)

from django.db.models import Q
# 找出定价低于20元 或 清华大学出版社的全部书
Book.objects.filter(Q(price__lt=20)|Q(pub='清华大学出版社'))
# 查找不是机械工业出版社的书且价格低于50的书
Book.objects.filter(Q(market_price__t=50) &~Q(pub_house='机械工业出版社'))

三、聚合查询和原生数据库操作

1、聚合查询

1整表聚合

  1. 导入方法from django.db.models import *
  2. 聚合函数Sum,Avg,Count,Max,Min
  3. 语法Mymodel.objects.aggregate(结果变量名=聚合函数('列'))
  4. 返回结果{‘结果变量名’:值}
Book.objects.aggregate(sumprice=Sum('price'))
# {'sumprice': Decimal('317.00')}

2分组聚合-先分组再聚合

  1. 通过查询values找到要分组聚合的列 MyModel.objects.values('列1','列2')
  2. 通过返回结果的QuerySet.annotate方法 QuerySet.annotate(名=聚合函数('列'))
pub_set = Book.objects.values('pub')
pub_count_set = pub_set.annotate(myCount=Count('pub'))
# <QuerySet [{'pub': '清华大学出版社', 'myCount': 3}, {'pub': '机械工业出版社', 'myCount': 2}]>

2、原生数据库操作

  • 直接用sql语句的方式进行数据库通信

1直接raw方法

  • 语法MyModel.objects.raw(sql语句,拼接参数)
  • 返回值RawQuerySet集合对象(只支持循环等基础操作)
  • 不推荐原因有SQL注入问题用户通过数据上传将恶意的sql语句提交给服务器从而达到攻击效果

在这里插入图片描述

# 案例1用户在搜索好友的表单框里输入'1 or 1=1',可查询出所有用户数据
books = Book.objects.raw('select * from book where id=%s'%('1 or 1=1'))
# 正确写法
books = Book.objects.raw('select * from book where id=%s',['1 or 1=1'])

2游标cursor

  1. 导入cursor所在的包 from django.db import connection
  2. 用创建cursor类的构造函数创建cursor对象
from django.db import connection
# with语句可保证在出现异常时释放cursor资源
with connection.cursor() as cur:
	cur.execute('sql语句','拼接参数')
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: go数据库