##################################################################
# PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET # 公共方法:通过操作属性,来返回一个新的queryset查询集
##################################################################
def all(self)
# 获取所有的数据对象 def filter(self, *args, **kwargs)
# 条件查询
# 条件可以是:参数,字典,Q def exclude(self, *args, **kwargs) #排除
# 条件查询
# 条件可以是:参数,字典,Q
class UserType(models.Model):
title = models.CharField(
max_length=
) class Person(models.Model):
user = models.CharField(
max_length=
) ut = models.ForeignKey(
to='UserType'
)

测试用数据库设计

性能相关:select_related,和prefetch_related

select_related:表之间进行join连表操作,一次性获取关联的数据。

普通方法获取数据:

   persion_list = models.Person.objects.all()

    for item in persion_list:
#是已经从person表中获取的数据
print(item.id,item.ut_id,item.user)
#需要再次从usertype中再去查询一次,又发了一次请求,执行的次数增加了,降低了数据库性能
print(item.ut.title)
使用select_related获取数据:
persion_list = models.Person.objects.all()
#一次性获取到所有数据(数据量大,占内存,只有需要连表时,才会去使用),
   #包含连表(select_related中,可以一次添加多个)的信息 select_related('','',...)
persion_list = models.Person.objects.all().select_related('ut')
  #select * from person left join usertype where person.ut_id = usertype.id   for item in persion_list:
#是已经从person表中获取的数据
print(item.id,item.ut_id,item.user)
#不会再去数据库中查询,因为数据已经取出来放在内存中
print(item.ut.title)

但是连表查询也会消耗一部分时间(连表查询性能低),在某些情况下,使用空间换取时间没来获得较小的查询时间。将连表放在同一张表中.

prefetch_related:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。分别在多个表中查询得到结果,然后重组。

使用prefetch_related获取数据:
persion_list = models.Person.objects.all()
#一次性获取到所有数据(数据量大,占内存,只有需要连表时,才会去使用),
   #prefetch_related('','',...)
persion_list = models.Person.objects.all().prefetch_related('ut')
  #相当于先去person表中select * from person ...(条件)
  #然后再去关联表中取数据:select * from usertype where id in [persion_list中的id列表],
  #Django将两者数据数据相结合,然后返回给用户,
  #此方法不使用连表,也是一次获取所有数据,高效
for item in persion_list:
#是已经从person表中获取的数据
print(item.id,item.ut_id,item.user)
#不会再去数据库中查询,因为数据已经取出来放在内存中
print(item.ut.title)

聚合查询:annotate(分组查询group by)请看:python---django中orm的使用(2)

去重函数:distinct

models.Persion.objects.all().distinct('name')   #查询姓名不重复的人

排序函数:order_by,可以设置多个值,排序先到后

persion_list = models.Person.objects.all().order_by('ut_id','-id') #-id代表id降序排序,默认升序排列

倒序函数:reverse将获取的数据集翻转倒序

persion_list = models.Person.objects.all().order_by('ut_id','-id').reverse()

获取单独字段:only和排除某些字段defer

only:
persion_list = models.Person.objects.only('id','user')
#select id,user from persion 只去获取这两个字段值。 注意:但是如果在后面获取数据的时候,获取其他值(不包含在id,user字段),也可以获取到,只是会再次去执行SQL语句 for item in persion_list:
print(item.ut_id,item.id,item.user)
#其中item.ut_id不在我们only字段中,所以会再次执行SQL语句去获取数据
  #SELECT "app02_person"."id", "app02_person"."ut_id" FROM "app02_person" WHERE "app02_person"."id" = ?; args=(item.id,)
defer:
persion_list = models.Person.objects.defer('ut_id') #效果一致同上面only

切换使用的数据库using:参数为使用的别名 def using(self, alias):

默认操作下会有models.Person.object.all().using("default') #在setting中设置
settings文件
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
  'default1': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite4'),
},
  'default2': { 
    'ENGINE': 'django.db.backends.mysql', #数据库引擎设置
    'NAME': 'test', #数据库名称
    'USER': 'root', #数据库用户名
    'PASSWORD':'root', #数据库密码
    'HOST':'', #主机地址,默认localhost
    'PORT':'' #数据库端口
  }
}

使用方式:

models.Person.object.all().using("default1') 使用第2种数据库去取数据
models.Person.object.all().using("default2') 使用第3种数据库引擎下数据库去取数据

额外的查询:extra:构造额外的查询条件或者映射

子查询:
#persion_list = models.Person.objects.extra(select={'new_tag':'select title from app02_usertype where id= %s'},select_params=(,))#无法实现动态
#SELECT (select title from app02_usertype where id= ) AS "new_tag", "app02_person"."id", "app02_person"."user", "app02_person"."ut_id" FROM "app02_person"; args=(,)
条件查询:
persion_list = models.Person.objects.extra(tables=['app02_usertype'],where=['app02_person.ut_id = app02_usertype.id'])
#SELECT "app02_person"."id", "app02_person"."user", "app02_person"."ut_id" FROM "app02_person" , "app02_usertype" WHERE (app02_person.ut_id = app02_usertype.id); args=()

##################################################
# PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS # 公共方法返回一个查询子集
##################################################

def values(self, *fields):
# 获取每行数据为字典格式 def values_list(self, *fields, **kwargs):
# 获取每行数据为元组 def dates(self, field_name, kind, order='ASC'):
# 根据时间进行某一部分进行去重查找并截取指定内容
# kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)
# order只能是:"ASC" "DESC"
# 并获取转换后的时间
- year : 年--
- month: 年-月-
- day : 年-月-日 models.DatePlus.objects.dates('ctime','day','DESC') def datetimes(self, field_name, kind, order='ASC', tzinfo=None):
# 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间
# kind只能是 "year", "month", "day", "hour", "minute", "second"
# order只能是:"ASC" "DESC"
# tzinfo时区对象
models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)
models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai')) """
pip3 install pytz
import pytz
pytz.all_timezones
pytz.timezone(‘Asia/Shanghai’)
""" def none(self):
# 空QuerySet对象

raw:执行原生SQL:

import pymysql

#创建连接
conn = pymysql.connect(host='127.0.0.1',port=,user='root',password='root',db='test',charset="utf8")
#创建游标
cursor = conn.cursor() effect_row = cursor.execute("insert into info (name,age,sex) values ('ls',33,'男')") conn.commit() cursor.close() conn.close()

pymysql操作数据库

import pymysql

conn = pymysql.connect(host="127.0.0.1",port=,user="root",password="root",db="prct",charset="utf8")

cursor = conn.cursor(pymysql.cursors.DictCursor)
#执行存储过程
cursor.callproc('p1') ret = cursor.fetchall() conn.commit()
cursor.close()
conn.close() print(ret)

pymysql操作数据库2  存储过程http://www.cnblogs.com/ssyfj/p/8545601.html

    from django.db import connection,connections
cursor = connections['default'].cursor()
cursor.execute("select * from app01_user where id > %s",[])
#select * from app01_user where id > ; args=[]
row = cursor.fetchall() print(row) #[(, u'\u674e\u56db'), (, u'\u738b\u4e94')]

Django执行原生SQL

执行原生SQL:
res = models.Person.objects.raw('select * from app02_person')
for item in res:
print(item) #Person object res = models.Person.objects.raw('select * from app01_user') #注意是可以去获取其他数据表的结果集,最好不要这样做,自己对应自己,不要乱用,易混淆
#select * from app01_user; args=()
#而且需要为这些联合表中重复字段设置别名,以免重复select id as nid,username from app01_user
  for item in res:
print(item) #Person object
设置参数:
models.Person.objects.raw('select id as nid,username from app01_user where nid >%s',params=[,])
转换列名:
name_map = {'username': 'un', }
res = models.Person.objects.raw('select id as nid,username from app01_user', translations=name_map)
指定数据库
models.Person.objects.raw('select * from app02_person', using="default")
####################################
# METHODS THAT DO DATABASE QUERIES #   进行数据库查询的方法
####################################
def count(self):
# 获取个数 def get(self, *args, **kwargs):
# 获取单个对象 def create(self, **kwargs):
# 创建对象
def first(self):
# 获取第一个 def last(self):
# 获取最后一个
def delete(self):
# 删除 def update(self, **kwargs):
# 更新

def set(self,**kwargs):
  #更新,将原来数据清除,重新设置为现在的数据(一对多,多对多)
def exists(self):
# 是否有结果
 
聚合函数:aggregatepython---django中orm的使用(2)
# 聚合函数,获取字典类型聚合结果
from django.db.models import Count, Avg, Max, Min, Sum
result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid'))
===> {'k': , 'n': }

aggregate

get_or_create:存在则获取,不存在则创建并返回该记录

    obj, created = models.Person.objects.get_or_create(user='root1',defaults={'ut_id': '',})
  # defaults 指定创建时,其他字段的值
  # 创建执行:INSERT INTO "app02_person" ("user", "ut_id") VALUES ('root1', ); args=[u'root1', ]
  # 查询执行:
SELECT "app02_person"."id", "app02_person"."user", "app02_person"."ut_id" FROM "app02_person" WHERE "app02_person"."user" = 'root1'; args=(u'root1',)
    print(obj)  #对应的记录(已有,则是原来的记录,原来没有,则是刚刚创建的数据记录)
print(created) #若是刚刚创建则为True,否则为False
update_or_create:如果存在,则更新,否则创建

    obj, created = models.Person.objects.update_or_create(user='root1',defaults={'ut_id': '',})
#BEGIN; args=None
#SELECT "app02_person"."id", "app02_person"."user", "app02_person"."ut_id" FROM "app02_person" WHERE "app02_person"."user" = 'root1'; args=(u'root1',)
#UPDATE "app02_person" SET "user" = 'root1', "ut_id" = WHERE "app02_person"."id" = ; args=(u'root1', , )

set补充:上面数据库是基于外键一对多,一个人的类型只能有一个,一个类型可以有多个人

下面进行多对多表修改:

class Tag(models.Model):
title = models.CharField(
max_length=
) class User(models.Model):
user = models.CharField(
max_length=
) ut = models.ManyToManyField(
to='Tag'
)

User对应Tag(多对多)

其中测试set:

    obj2 = models.User.objects.filter(id=).first()
obj2.ut.set(,) #若是原来是1,2则会被修改为2,

也可以用外键进行测试需要使用外键方来进行修改,否则一些方法无法找到:

    obj2 = models.Person.objects.filter(id__gt=)
obj1.ut.all()
#错误,没有该属性,person是多,对应只有一,是一个单独的对象
  #obj1.ut.all() #AttributeError at /test2 'UserType' object has no attribute 'all'
  print(type(obj1))
  #<class 'app02.models.Person'>
   obj2 = models.UserType.objects.filter(id=).first()
 print(obj2.person_set.all())
#正确,usertype是一,对应多,获取的数据是一个数据集,queryset
    # print(type(obj2))  
   #<QuerySet [<Person: Person object>, <Person: Person object>, <Person: Person object>, <Person: Person object>,<Person: Person object>]>, <class 'app02.models.UserType'>)
 

ORM的事务操作

一:导入模块

from django.db import transaction

二:简单使用

        try:
with transaction.atomic():
表的增删改操作 except Exception as e:
return HttpResponse("出现错误....")
return HttpResponse("ok")

python---django中orm的使用(5)数据库的基本操作(性能相关:select_related,和prefetch_related重点)(以及事务操作)的更多相关文章

  1. 6月20日 Django中ORM介绍和字段、字段参数、相关操作

    一.Django中ORM介绍和字段及字段参数 二.Django ORM 常用字段和参数 三.Django ORM执行原生SQL.在Python脚本中调用Django环境.Django终端打印SQL语句 ...

  2. 关于Django中ORM数据库迁移的配置

    Django中ORM数据库迁移配置 1,若想将模型转为mysql数据库中的表,需要在settings中配置: DATABASES = { 'default': { 'ENGINE': 'django. ...

  3. Django中ORM对数据库的增删改查

    Django中ORM对数据库数据的增删改查 模板语言 {% for line in press %} {% line.name %} {% endfor %} {% if 条件 %}{% else % ...

  4. Django中ORM介绍和字段及其参数

    ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述 ...

  5. Django中ORM介绍和字段及字段参数 Object Relational Mapping(ORM)

    Django中ORM介绍和字段及字段参数   Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简 ...

  6. Django 中ORM 的使用

    一:Django 中 orm 的使用 1:手动新建一个数据库 2 :告诉Django连接哪个数据库 settings.py里配置数据库连接信息: #数据库相关的配置项 DATABASES ={ 'de ...

  7. Django中ORM的使用

    Django中ORM的使用 ORM orm(object-relation-mapping)对象关系映射,即用对象来表示关系数据库中的表: 类 --> 表, 对象-->一行数据 对象的属性 ...

  8. Django中ORM实际应用

    1. Django中ORM的使用 1. 手动新建一个数据库 2. 告诉Django连接哪个数据库 settings.py里面配置数据库连接信息: # 数据库相关的配置项 DATABASES = { ' ...

  9. Django中ORM简述

    ORM:对象关系映射(Object Relational Mapping,简称ORM) 作用:根据类生成表结构,将对象.列表的操作转换成对象的SQL语句,将SQL语句查询的结果转换为对象或列表 优点: ...

随机推荐

  1. 你应该知道Go语言的几个优势

    要说起GO语言的优势,我们就得从GO语言的历史讲起了-- 本文由腾讯技术工程官方号发表在腾讯云+社区 2007年,受够了C++煎熬的Google首席软件工程师Rob Pike纠集Robert Grie ...

  2. 虚拟机console最小化安装操作系统图文

    1. 概述2. 安装操作系统2.1 交互界面2.2 内核镜像解压等初始化2.3 磁盘发现2.4 硬件支持告警3. 开始安装3.1 语言选择3.2 键盘选择3.3 服务器类型3.4 配置主机名3.5 时 ...

  3. fiddler之会话数据的修改

    fiddler之会话数据的修改 fiddler记录http的请求,并且针对特定的http请求,可以分析请求数据.修改数据.调试web系统等,功能十分强大.本篇主要讲两种修改的数据的方法,断点和Unlo ...

  4. idou老师教你学Istio: 如何用Istio实现K8S Egress流量管理

    本文主要介绍在使用Istio时如何访问集群外服务,即对出口流量的管理. 默认安装的Istio是不能直接对集群外部服务进行访问的,如果需要将外部服务暴露给 Istio 集群中的客户端,目前有两种方案: ...

  5. Nextcloud13私有云盘安装指南

    一.环境说明: ※操作系统版本CentOS 7.5 Minimal-1804 ※操作系统版本已经使用163 YUM源 ※ Nextcloud版本 13.05 ※ 数据库使用MariaDB,安装在同一台 ...

  6. maven util 类 添加 service

    直接关键代码: public class DictionaryUtil { // 以下的处理,是为了在工具类中自动注入service // 前提是在applicationContext.xml中,将该 ...

  7. CSAPP lab2 二进制拆弹 binary bombs phase_2

    给出对应于7个阶段的7篇博客 phase_1  https://www.cnblogs.com/wkfvawl/p/10632044.htmlphase_2  https://www.cnblogs. ...

  8. 第二个spring冲刺第4天

    今天,我们团队参考了其他团队的四则运算的程序,发现很多地方可以学习. 1.别人的界面比较唯美,我们做的有点粗糙,所以这个必须要改善. 2.别人的具有较多的功能,比如计时器,我们要效仿. 3.还有难度选 ...

  9. 基于 Java Web 的毕业设计选题管理平台--测试报告与用户手册

    一.测试报告 1.兼容性测试 功能 描述 效果 Chrome浏览器 FireFox浏览器 IE浏览器 war 端浏览器 管理员登录 管理员用户登录功能 弹出“登录成功”对话框,进入到毕业设计选题管理平 ...

  10. 第三周作业:Visual Studio 2013

    在装Visual Studio 2013的时候,提示我升级我的电脑,不然不给安装,于是我就各种升级,完事之后有了这个: 在我耐心的等待之下终于等到安装完成: 我就建立一个新的项目: 我就写了一个简单程 ...