Django ORM 单表操作

x33g5p2x  于2022-03-03 转载在 Go  
字(8.1k)|赞(0)|评价(0)|浏览(271)


ORM操作单表,逆向输出SQL,一篇长文就get~

Django ORM单表操作

Django 测试环境搭建

注意pycharm链接数据库都需要提前下载对应的驱动,自带的sqlite3对日期格式数据不敏感,如果后续业务需要使用日期辅助筛选数据那么不推荐使用sqlite3

搭建方式

  1. 任意创建一个py文件,在该文件内书写固定的配置
import os
if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day06.settings")
    import django
    django.setup()
  1. 直接使用pycharm提供的python console

ORM 创建表

# Mysql配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'orm_simple',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': 'root',
        'CHARSET':'utf8'
    }
}
'''__init__.py'''
import pymysql
pymysql.install_as_MySQLdb()

创建表

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5,decimal_places=2)
    publish = models.CharField(max_length=32)
    publish_data = models.DateField()  # 出版时间
# 路由
from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('book/', views.book),
]

ORM 添加数据

有两种添加数据的方式:

  • **方式一:**模型类实例化对象
  • **方式二:**通过 ORM 提供的 objects 提供的方法 create 来实现(推荐)
from django.shortcuts import render,HttpResponse
from app01 import models

def book(request):
    '''添加数据的两种方式'''
    # 方式1
    book_obj = models.Book(title='Python',price='99',publish='Hammer出版社',publish_data='2022-2-2')
    book_obj.save()
    # 方式2    
    models.Book.objects.create(title='Java',price='88',publish='Hans出版社',publish_data='2021-2-1')
    return HttpResponse('<p>数据添加成功</p>')

ORM 查询数据

all 查询

all()方法查询所有数据,返回一个QuerySet对象,类似list,可以通过索引来获取列表中的对象,这里不支持负索引

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

def book(request):
    book_obj = models.Book.objects.all()
    print(book_obj)   # <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]>
    print(book_obj[0])   # Book object (1)
    print(book_obj.first())  # Book object (1) 等价于[0]
    print(book_obj.first().title) # Python 获取值
    return HttpResponse('<p>数据查询成功</p>')

filter 查询

filter() 方法用于查询符合条件的数据

返回的是 QuerySet 类型数据,类似于 list,里面放的是满足条件的模型类的对象,可用索引下标取出模型类的对象;

def book(request):
    book_obj = models.Book.objects.filter(pk=2)
    print(book_obj)
    print(book_obj.first().title)  # JavaScript
    book_obj1 = models.Book.objects.filter(title='JavaScript',price='99')
    print(book_obj1.first().pk)  # 2
    return HttpResponse('<p>数据查询成功</p>')

exclude 取反查询

exclude() 方法用于查询不符合条件的数据,返回的是 QuerySet 类型数据,类似于 list,里面放的是不满足条件的模型类的对象,可用索引下标取出模型类的对象;

def book(request):
    book_obj = models.Book.objects.exclude(pk=2)
    print(book_obj)  # <QuerySet [<Book: Python>, <Book: C>, <Book: PHP>, <Book: C++>, <Book: 数据结构>]>
    for i in book_obj.all():
        print(i.title)  # Python C  PHP C++ 数据结构
    return HttpResponse('<p>数据查询成功</p>')

get 查询

get() 方法用于查询符合条件的返回模型类的对象符合条件的对象只能为一个,如果符合筛选条件的对象超过了一个或者没有一个都会抛出错误

区别filter()如果获取不到符合条件的数据,返回一个空对象,不报错

from django.shortcuts import render,HttpResponse

from app01 import models
def book(request):
    book_obj = models.Book.objects.get(pk=1)
    print(book_obj)
    return HttpResponse('<p>数据查询成功</p>')

order_by 排序

order_by() 方法用于对查询结果进行排序,返回的是 QuerySet类型数据,类似于list,里面放的是排序后的模型类的对象,可用索引下标取出模型类的对象

  • 参数的字段名要加引号
  • 降序为在字段前面加个负号 -
def book(request):
    # 升序排序
    book_obj = models.Book.objects.order_by('id')
    for i in book_obj:
        print(i.title)  # Python  JavaScript C PHP C++ 数据结构
    # 降序排序
    book_obj1 = models.Book.objects.order_by('-id')
    for i in book_obj1:
        print(i.title)  # 数据结构 C++ PHP C JavaScript Python 
    return HttpResponse('<p>数据查询成功</p>')

reverse 反转

reverse() 方法用于对查询结果进行反转,返回的是 QuerySe t类型数据,类似于 list,里面放的是反转后的模型类的对象,可用索引下标取出模型类的对象

使用反转函数前先排序

def book(request):
    # 按照价格升序排列:降序再反转
    books = models.Book.objects.order_by("-price").reverse()
    return HttpResponse("<p>查找成功!</p>")

count 汇总数量

count() 方法用于查询数据的数量返回的数据是整数

def book(request):
    book_obj = models.Book.objects.count()
    print(book_obj) # 查询所有数据的数量>>>6
    book_obj1 = models.Book.objects.filter(price=200).count() # 查询符合条件数据的数量
    return HttpResponse('<p>数据查询成功</p>')

exists 判断

exists() 方法用于判断查询的结果 QuerySet 列表里是否有数据,返回的数据类型是布尔,有为 true,没有为 false。

from django.shortcuts import render,HttpResponse
from app01 import models
def book(request):
    books = models.Book.objects.exists()
  	# True
    books = models.Book.objects.count().exists()
     # 报错,判断的数据类型只能为QuerySet类型数据,不能为整型
    books = models.Book.objects.first().exists()  
     # 报错,判断的数据类型只能为QuerySet类型数据,不能为模型类对象
    return HttpResponse("<p>查找成功!</p>")

values 查询字段

返回的是 QuerySet 类型数据,类似于 list,里面不是模型类的对象,而是一个可迭代的字典序列,字典里的键是字段,值是数据

def book(request):
    book_obj = models.Book.objects.values('price','title')
    print(book_obj)  # 返回所有price和title字段,以列表套字典的形式
    # <QuerySet [{'price': Decimal('99.00'), 'title': 'Python'}]
    book_obj1 = models.Book.objects.filter(pk=1).values('title')
    print(book_obj1,book_obj[0].get('title'))  # <QuerySet [{'title': 'Python'}]>  Python
    return HttpResponse('<p>数据查询成功</p>')

values_list 查询部分字段

values_list() 方法用于查询部分字段的数据,values_list() 方法用于查询部分字段的数据

def book(request):
    book_obj = models.Book.objects.values_list('price','title')
    print(book_obj)  # 返回所有price和title字段,以列表套元组的形式
    # <QuerySet [(Decimal('99.00'), 'Python')]
    for title in book_obj:
        print(title[1]) # 获取所有title
    return HttpResponse('<p>数据查询成功</p>')

values和values_list区别

  • values查询返回的结果是列表套字典的形式,字段名和数据都能够获取到
  • values_list查询返回的结果是列表套元组的形式,只返回数据

distinct 去重

distinct() 方法用于对数据进行去重,返回的是 QuerySet 类型数据

注意:

  • 对模型类的对象去重没有意义,因为每个对象都是一个不一样的存在(主键不一样),去重的前提是数据必须是一模一样,不能加主键,有unique的也没意义
  • distinct() 一般是联合 values 或者 values_list 使用
from django.shortcuts import render,HttpResponse
from app01 import models
def book(request):
    # 查询一共有多少个出版社
    books = models.Book.objects.values_list("publish").distinct() # 可以去重
    books = models.Book.objects.distinct()
    # 对模型类的对象去重没有意义,因为每个对象都是一个不一样的存在,主键不一样
    return HttpResponse("<p>查找成功!</p>")

ORM 双下划线方法

__in

类似sql的成员运算,用于读取区间,= 号后面为列表

**注意:**filter 中运算符号只能使用等于号 = ,不能使用大于号 > ,小于号 < ,等等其他符号

  • 格式:字段__in = [a,b]
def book(request):
    book_obj = models.Book.objects.filter(price__in=[100,300])
    print(book_obj)  # <QuerySet [<Book: Book object (2)>, <Book: Book object (22)>]>
    return HttpResponse('<p>数据查询成功</p>')

__gt __gte

大于、大于等于

# 价格大于100的数据
book_obj = models.Book.objects.filter(price__gt=100)
# 价格大于等于100的数据
book_obj = models.Book.objects.filter(price__gte=100)

__lt __lte

小于、小于等于

# 价格小于100的数据
book_obj = models.Book.objects.filter(price__lt=100)
# 价格小于等于100的数据
book_obj = models.Book.objects.filter(price__lte=100)

__range

表示范围,在···之间,类似sql的between··and,左闭右区间,= 号后面为两个元素的列表

# 价格在100到200之间的数据
book_obj = models.Book.objects.filter(price__range=[100,300])

__contains

包含关系,=号后面为字符串,类似sql的模糊查询,LIKE

# 查询包含Py字符的书名
book_obj = models.Book.objects.filter(title__contains='Py')

__icontains

不区分大小写,和contains一样

# 查询包含Py字符的书名
book_obj = models.Book.objects.filter(title__contains='py')

__startswith

查询以指定字符开头,= 号后面为字符串

book_obj = models.Book.objects.filter(title__startswith='P')

__endswith

查询以指定字符结尾,=号后面为字符串

book_obj = models.Book.objects.filter(title__endswith='构')

__year

__year 是 DateField 数据类型的年份,= 号后面为数字

# 2022年出版的数据
book_obj = models.Book.objects.filter(publish_date__year=2022)

__month

查询月份

# 3月出版的数据
book_obj = models.Book.objects.filter(publish_date__month=3)

__day

__day 是DateField 数据类型的天数,= 号后面为数字

# 所有17号出版的数据
book_obj = models.Book.objects.filter(publish_date__day=17)

ORM 删除数据

**方式一:**使用模型类的 对象.delete()

**返回值:**元组,第一个元素为受影响的行数

book_obj=models.Book.objects.filter(pk=8).first().delete()

方式二:使用 QuerySet 类型数据.delete()(推荐)

**返回值:**元组,第一个元素为受影响的行数。

books=models.Book.objects.filter(pk__in=[1,2]).delete()

注意:

  • Django 删除数据时,会模仿 SQL约束 ON DELETE CASCADE 的行为,也就是删除一个对象时也会删除与它相关联的外键对象;
  • delete() 方法是 QuerySet 数据类型的方法,但并不适用于 Manager 本身。也就是想要删除所有数据,不能不写 all;

ORM 修改数据

方式一:

模型类的对象.属性 = 更改的属性值
模型类的对象.save()
def book(request):
    book_obj = models.Book.objects.filter(pk=23).first()
    print(book_obj)
    book_obj.title='如何傍富婆,从入门到入赘'
    book_obj.save()
    return HttpResponse('<p>入赘成功</p>')

**方式二:**QuerySet 类型数据.update(字段名=更改的数据)(推荐)

**返回值:**整数,受影响的行数

def book(request):
    book_obj = models.Book.objects.filter(pk=23).update(title='人活一口气,打死不入赘')
    return HttpResponse(book_obj) # 1

ORM 逆转到 SQL

方式一:

如果想打印orm转换过程中的sql,需要在settings中进行如下配置:

'''settings.py'''
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

ps:本质是日志的监控,可以在test下测试

方式二:使用对象.query获取原生SQL()

from app01 import models
res = models.Book.objects.filter(pk=2)
print(res.query)

'''
SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`publish`, `app01_book`.`publish_date` FROM `app01_book` WHERE `app01_book`.`id` = 2
'''

相关文章