django基础 -QuerySet API
 

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

文章作者: 以谁为师
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源!
              
  目录