Django的ORM框架中从数据库中查询出来的结果一般是一个集合,这个集合叫做 QuerySet。
QuerySet 查询
交互shell
python manage.py shell
# 进入django交互shell
创建数据
from django.contrib.auth.models import User
User.objects.all() #查看所有用户
User.objects.create_superuser(username="admin", password=pwd, email="admin@qq.com")
# 创建admin
user=User.objects.get(username='admin')
user.set_password('new_password') # 替换密码
user.save() # 用save方法保存对象
基础查询
from blog.models import *
Article.objects.all()
# 查询所有数据
模糊查询
from django.db.models import Q
Article.objects.filter(Q(title__icontains=key) | Q(body__icontains=key)).order_by('-click_count')
# 查询标题和内容字段数据,并按`click_count'`点击排名排序
取值范围
from blog.models import *
Article.objects.all()[:3] # 切片操作,前10条
Article.objects.all()[-10:] # 会报错,不支持负索引!
# 1. 使用 reverse() 解决
Article.objects.all().reverse()[:2] # 最后两条
Article.objects.all().reverse()[0] # 最后一条
# 2. 使用 order_by,在栏目名(column name)前加一个负号
Article.objects.order_by('-id')[:20] # id最大的20条
查询拼接
合并到一起(Model相同,而且没有用切片,并且字段一样)
qs1 = Pathway.objects.filter(label__name='x')
qs2 = Pathway.objects.filter(reaction__name='A + B >> C')
qs3 = Pathway.objects.filter(inputer__name='WeizhongTu')
# 合并
qs = qs1 | qs2 | qs3
# 去重的方法
qs = qs.distinct()
chain 合并查询集
返回结果:优先查询到标题结果,内容匹配结果次之 chain 方法来合并多个list. 即使不同的MODEL中查询的数据,也可以合并到一个 list;chain 本身是用C实现的性能上也比较可靠
from itertools import chain
class SearchView(PaginationMixin, generic.ListView):
model = Article
template_name = "search.html"
paginate_by = 10 # 记录数量
# 返回查询记录
def get_queryset(self):
key = self.request.GET.get('q')
if key:
articles1 = Article.objects.filter(title__icontains=key).order_by('-click_count') # 按点击率排序
articles2 = Article.objects.filter(body__icontains=key).order_by('-click_count')
data = chain(articles1, articles2) # chain()可以把一组迭代对象串联起来,形成一个更大的迭代器
# context = [iterm for iterm in data] # 没有len方法。需要使用列表生成式重新赋值
context = []
[context.append(i) for i in data if i not in context] # 使用列表推导式去重
return context
链式过滤
`filter`和`exclude`的结果依然是个QuerySet,因此它可以继续被filter和exclude,这就形成了链式过滤
```python
Entry.objects.filter(
... headline__startswith='What'
... ).exclude(
... pub_date__gte=datetime.date.today()
... ).filter(
... pub_date__gte=datetime(2005, 1, 30)
... )
### F表达式对算术操作
返回发布时间超过3天后被修改的所有Entry结果
```python
from datetime import timedelta
Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
原生SQL语句
django raw执行sql
sql语句
SELECT * FROM blog_article ORDER BY id DESC LIMIT 1
django 执行sql
sql=Article.objects.raw("SELECT * FROM blog_article ORDER BY id DESC LIMIT 1")
# 返回RawQuerySet数据列表
sql.model # 查看model名称
sql.columns # 查看sql结果中的列字段
sql.raw_query # 重现sql查询语句
[s for s in sql] # 查看结果
[s.title for s in sql] # 打印所有标题
向 raw() 传递参数
如果你需要执行带参数的查询,你可以使用 params 参数
lname = 'Doe'
Person.objects.raw("SELECT * FROM myapp_person WHERE last_name = %s", [lname])
# params 是一个参数列表。在查询字符串中你要使用 %s 占位符(不管你用何种数据库引擎)。占位符会被 params 列表中的参数代替。
query = 'SELECT * FROM myapp_person WHERE last_name = %s' % lname
Person.objects.raw(query)
# Warning ! 不要在原始查询中使用格式化字符串!千万不要这样写 !
# 使用 params 列表可以保护你避开 SQL 注入攻击 (通过漏洞把恶意 SQL 注入你的数据库)。如果你使用了字符串直接插入,那么会成为 SQL 注入的受害者,因此要谨记使用 params 列表。
执行自定义SQL
( 这种方式完全不依赖model,前两种还是要依赖于model;直接执行自定义SQL,这种方式可以完全避免数据模型,而是直接执行原始的SQL语句。 )
from django.db import connection
with connection.cursor() as cur:
# 删除 id为1的一条记录
cur.execute('delete from bookstore_book where id=10;')
with connection.cursor() as cursor:
# 执行sql文件
with open("./update.sql") as f:
for raw in f:
cursor.execute(raw.strip()) # 执行sql
print (cursor.fetchone()) # 返回结果行游标直读向前,读取一条
print(cursor.fetchall) # 读取所有sql