Python全栈之路-Django(九)
1 ORM操作
1.常用ORM操作
models.UserInfo.objects.all()
models.UserInfo.objects.filter(id=1,name='wyz') # filter内的条件为and
models.UserInfo.objects.first() # 不是一个QuerySet对象
models.UserInfo.objects.count() # 计算行数
models.UserInfo.objects.create()
models.UserInfo.objects.update()
models.UserInfo.objects.delete()
models.UserInfo.objects.all()[start,end] # limit
models.UserInfo.objects.all().values(x,y,...)
models.UserInfo.objects.filter(id__gt=1).values_list(x,y,...)
# QuerySet可以调用.values、.values_list
2.其他
app01.models.py
from django.db import models
# Create your models here.
class UserType(models.Model):
title = models.CharField(max_length=32)
class UserInfo(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
ut = models.ForeignKey('UserType')
def __str__(self):
return "%s-%s" % (self.id, self.name)
app01.views.py
# 数据库操作
from app01 import models
def test(request):
# http://www.cnblogs.com/wupeiqi/articles/6216618.html
# 排序
user_list = models.UserInfo.objects.all().order_by('id') # 升序
print(user_list)
user_list = models.UserInfo.objects.all().order_by('-id') # 降序 '-' 代表降序
print(user_list)
user_list = models.UserInfo.objects.all().order_by('-id','name') # 按照id降序,按照name升序
print(user_list)
# 分组
# 1. 不带where和having条件的分组
from django.db.models import Count, Sum, Max, Min
# v = models.UserInfo.objects.values('ut_id').annotate(xxx=Count('id'))
# print(v.query)
# # SELECT "app01_userinfo"."ut_id", COUNT("app01_userinfo"."id") AS "xxx" FROM "app01_userinfo" GROUP BY "app01_userinfo"."ut_id"
# 2. 带having条件的分组
# v = models.UserInfo.objects.values('ut_id').annotate(xxx=Count('id')).filter(xxx__gt=2)
# print(v.query)
# # SELECT "app01_userinfo"."ut_id", COUNT("app01_userinfo"."id") AS "xxx" FROM "app01_userinfo" GROUP BY "app01_userinfo"."ut_id" HAVING COUNT("app01_userinfo"."id") > 2
# 3. 带where和having条件的分组
v = models.UserInfo.objects.values('ut_id').filter(id__gt=2).annotate(xxx=Count('id')).filter(xxx__gt=2)
print(v.query)
# SELECT "app01_userinfo"."ut_id", COUNT("app01_userinfo"."id") AS "xxx" FROM "app01_userinfo" WHERE "app01_userinfo"."id" > 2 GROUP BY "app01_userinfo"."ut_id" HAVING COUNT("app01_userinfo"."id") > 2
# in range startswith endswith contains
models.UserInfo.objects.filter(id__in=[1,2,3])
models.UserInfo.objects.filter(id__range=[1,3])
models.UserInfo.objects.filter(name__startswith="xxx")
models.UserInfo.objects.filter(name__endswith="xxx")
models.UserInfo.objects.filter(name__contains="xxx")
# 不等于 id != 1
models.UserInfo.objects.exclude(id=1)
# F
from django.db.models import F
# 所有人的年龄加一
# F是用来做更新时获取该字段原始的值
# models.UserInfo.objects.all().update(age=F("age")+1)
# Q
# Q是用来解决一些查询问题 用于构造复杂的查询条件
models.UserInfo.objects.filter(id=1, name='root')
# 上面的写法可以用以下代码代替,即把条件写到一个字典中,但是默认还是用and
condition = {
'id': 1,
'name': 'root'
}
models.UserInfo.objects.filter(**condition)
from django.db.models import Q
# 第一种写法 对象方式
# | 表示or & 表示and
models.UserInfo.objects.filter(Q(id=1))
models.UserInfo.objects.filter(Q(Q(id=1) | Q(name='root')))
models.UserInfo.objects.filter(Q(Q(id=1) & Q(name='root')))
# 第二种写法 方法方式 推荐使用
con = Q()
q1 = Q()
q1.connector = 'OR'
q1.children.append(('id', 1))
q1.children.append(('id', 10))
q1.children.append(('id', 9))
q2 = Q()
q2.connector = 'OR'
q2.children.append(('name', 'root'))
q2.children.append(('name', 'wyz'))
q2.children.append(('name', 'shz'))
con.add(q1, 'AND')
con.add(q2, 'AND')
# (id=1 or id=10 or id=9) and (c1=1 or c1=10 or c1=9)
models.UserInfo.objects.filter(con)
# 通过字典动态添加
condition_dict = {
'k1': [1, 2, 3, 4],
'k2': [12],
'k3': [13, 14],
}
con = Q()
for k, v in condition_dict:
q = Q()
q.connector = 'OR'
for i in v:
q.children.append(('id', i))
con.add(q, 'AND')
models.UserInfo.objects.filter(con)
# extra 额外的查询条件以及相关表和排序操作
"""
select id,name,(select count(1) from tb) as n from tb;
"""
# select自定义列 & select_params & order_by
v = models.UserInfo.objects.all().extra(
select={
'n': "select count(1) from app01_userinfo where id>%s and id < %s",
'm': "select count(1) from app01_userinfo where id>%s and id < %s"
},
select_params=[1, 5, 2, 4], order_by=['-id']
)
for obj in v:
print(obj.name, obj.id, obj.n, obj.m)
# where条件 & select_params
models.UserInfo.objects.extra(
where=['id=%s or id=%s', 'name="%s"'],
select_params=[1, 2, 'root']
)
# 笛卡尔积
models.UserInfo.objects.extra(
tables=['app01_usertype'],
where=['app01_usertype.id = app01_userinfo.ut_id']
)
# extra 应用及SQL语句转换
"""
models.UserInfo.objects.extra(
select={'newid':'select count(1) from app01_usertype where id>%s'},
select_params=[1,],
where = ['age>%s'],
params=[18,],
order_by=['-age'],
tables=['app01_usertype']
)
select
app01_userinfo.id,
(select count(1) from app01_usertype where id>1) as newid
from app01_userinfo,app01_usertype
where
app01_userinfo.age > 18
order by
app01_userinfo.age desc
"""
# 原生SQL语句
from django.db import connection, connections
# settings.py
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# },
# 'db2': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db2.sqlite3'),
# }
# }
# cursor = connection.cursor() # connection=default数据
cursor = connections['db2'].cursor() # 自定义连接数据库
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
row = cursor.fetchone()
row = cursor.fetchall()
# ORM补充
# distinct去重
models.UserInfo.objects.values('id').distinct()
# select distinct id from userinfo
# 连接PostgreSQL写法:
# models.UserInfo.objects.distinct('id')
# 倒序
# 如果没有order_by,则reverse没有任何作用
models.UserInfo.objects.all().order_by('-id').reverse()
# 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序
# 仅取某个表中的数据
# only
models.UserInfo.objects.only('name', 'id')
# 或
models.UserInfo.objects.filter(...).only('name', 'id')
# defer
models.UserInfo.objects.defer('name', 'id')
# 或
models.UserInfo.objects.filter(...).defer('name', 'id')
# 映射中排除某列数据
# using
# 指定使用的数据库,参数为别名(setting中的设置)
models.UserInfo.objects.all().using('db2')
# QuerySet类型可以无限往下. values values_list后面就不能.了
# date
# 根据时间进行某一部分进行去重查找并截取指定内容
# kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)
# order只能是:"ASC" "DESC"
# 并获取转换后的时间
# - year: 年 - 01 - 01
# - month: 年 - 月 - 01
# - day: 年 - 月 - 日
# models.DatePlus.objects.dates('ctime', 'day', 'DESC')
# datetimes
# 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间
# 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’)
# """
# none
# 空QuerySet对象
models.UserInfo.objects.none()
# aggregate
# 聚合函数,获取字典类型聚合结果
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': 3, 'n': 4}
# get
models.UserInfo.objects.get(id=1)
# get的缺点,获取不到值会抛异常,获取到多个值也会抛异常 所以建议用first
# create 接字典格式参数
obj = models.UserInfo.objects.create(**{'title': 'xxx'})
# 对比 obj = models.UserInfo.objects.create(title='xxx')
# obj为创建的最后一条数据
# obj.id 为自增id列
# 其他创建方式
# obj = models.UserInfo(title='xxx')
# obj.save()
# bulk_create
# 批量插入
# batch_size表示一次插入的个数 建议不超过999
# objs = [
# models.DDD(name='r11'),
# models.DDD(name='r22')
# ]
# models.DDD.objects.bulk_create(objs, 10)
# update_or_create
# 如果存在,则更新,否则,创建
# defaults 指定创建时或更新时的其他字段
# obj, created = models.UserInfo.objects.update_or_create(
# username='root1',
# defaults={'email': '1111111', 'u_id': 2, 't_id': 1}
# )
# obj创建成功的对象
# get_or_create
# 如果存在,则获取,否则,创建
# defaults 指定创建时,其他字段的值
obj, created = models.UserInfo.objects.get_or_create(
username='root1',
defaults={'email': '1111111', 'u_id': 2, 't_id': 2}
)
# update_or_create get_or_create 除了default指定的参数其他都是查询条件,并且为and
# in_bulk
# 根据主键ID进行查找
# id_list = [11, 21, 31]
# models.DDD.objects.in_bulk(id_list)
# raw
# 执行原生SQL
# models.UserInfo.objects.raw('select * from userinfo')
#
# # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名
# models.UserInfo.objects.raw('select id as nid from 其他表')
#
# # 为原生SQL设置参数
# models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12, ])
#
# # 将获取的到列名转换为指定列名
# name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
# Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)
#
# # 指定数据库
# models.UserInfo.objects.raw('select * from userinfo', using="default")
#exists
# 是否有结果 返回bool值
return HttpResponse('...')
3 XSS攻击
1.html模板中慎用safe 和 mark_safe
2.一定要用,一定要过滤关键字