【Django-ninja】django ninja中使用查询过滤器FilterSchema

Django ORM中过滤器

filter的基本用法

filter() 是 QuerySet 对象的一个方法,用于从数据库中过滤数据。它接受一个或多个关键字参数,每个参数都表示一个查询条件,它们之间是 AND 关系。

以下是 filter() 方法的基本用法示例:

python 复制代码
from myapp.models import MyModel

# 查询所有 name 字段值为 'John' 的记录
results = MyModel.objects.filter(name='John')

# 查询所有 age 大于等于 25 的记录
results = MyModel.objects.filter(age__gte=25)

# 多个条件的 AND 关系
results = MyModel.objects.filter(name='John', age__gte=25)

# 使用 OR 条件,使用 Q 对象
from django.db.models import Q
results = MyModel.objects.filter(Q(name='John') | Q(age__gte=25))

上述示例中,MyModel 是一个数据库模型,filter() 方法用于根据指定的查询条件过滤数据库中的记录。其中:
2. (1) name='John' 表示查询 name 字段等于 'John' 的记录。

  1. (2) age__gte=25 表示查询 age 字段大于等于 25 的记录。

  2. (3) 多个条件之间是 AND 关系,即同时满足所有条件。

  3. (4) 使用 Q 对象可以实现 OR 关系,其中 Q(name='John') | Q(age__gte=25) 表示查询 name 字段等于 'John' 或 age 字段大于等于 25 的记录。

**Django中的常用过滤器

基本查询过滤器:**

  • exact: 等于,例如 field__exact=value
  • iexact: 不区分大小写的等于,例如 field__iexact=value
  • contains: 包含,例如 field__contains=value
  • icontains: 不区分大小写的包含,例如 field__icontains=value
  1. 范围查询过滤器:

    • gt: 大于,例如 field__gt=value
    • lt: 小于,例如 field__lt=value
    • gte: 大于等于,例如 field__gte=value
    • lte: 小于等于,例如 field__lte=value
  2. 空值查询过滤器:

    • isnull: 是否为空,例如 field__isnull=True
  3. IN 查询过滤器:

    • in: 在某个列表中,例如 field__in=[value1, value2]
  4. 日期查询过滤器:

    • date: 根据日期进行查询,例如 pub_date__date=some_date, pub_date__contains="2024-01"
  5. 时间查询过滤器:

    • time: 根据时间进行查询,例如 pub_time__time=some_time
  6. 外键查询过滤器:

    • ForeignKeyField__fieldname: 对于外键关系,可以使用 __ 来查询相关字段,例如 author__name__icontains=value
  7. 组合查询过滤器:

    • &(与)和 |(或):可以使用 &| 符号来组合多个查询条件,例如 Q(field1=value1) | Q(field2=value2)

2. django-ninja过滤器FilterSchema的用法

为什么已经有了Django ORM中的filter函数,还有整出个Django-ninja过滤器呢?

因为一般来说,从客户端用户发来一个请求,往往会带有很多查询参数。通过查询参数,在数据库中查找对应的记录。这些查询参数往往也并不是固定的。

如果我们直接通过手写代码构造filter需要的过滤条件,代码会相当丑陋,变得很难维护。

django-nina过滤器FilterSchema的作用就是对用户查询条件到数据库查询条件这一个过程的封装。

Django ORM的filter关心数据库的数据,而Django Ninja的过滤器关心用户与我们网站互动的方式。

2.1 基础用法

python 复制代码
from ninja import FilterSchema, Field
from typing import Optional


class BookFilterSchema(FilterSchema):
    name: Optional[str] = None
    author: Optional[str] = None
    created_after: Optional[datetime] = None
python 复制代码
@api.get("/books")
def list_books(request, filters: BookFilterSchema = Query(...)):
    books = Book.objects.all()
    books = filters.filter(books)
    return books

2.2 一个稍微复杂一点的用法

自定义的过滤器继承FilterSchema。

  1. filter_title_list方法用于处理title_list参数
python 复制代码
class BookFilterSchema(FilterSchema):
    """ 过滤器用于从用户的请求参数,转化为查询的过滤条件。
    1. 默认使用类pub_date, title等字段进行过滤
    2. 如果不能满足条件,可以使用自定义的函数对某一个参数编写函数进行过滤,函数名称使用filter_开头
    3. 如果还不能满足要求,可以使用custom_expression定义一个完整的过滤查询器。这时候其他内置的
        查询条件都会被忽略掉。
    """
    pub_date: date = Field(None)  # 默认值为None,不使用这个过滤器
    # title__in: List[str] = Field(None, alias="titles")
    title: str = Field(None)
    title_list: str = Field(None)  # 传输参数
    search: Optional[str] = Field(None, q=['title__icontains',
                                           'pub_date__date'])

    def custom_expression(self) -> Q:
        """ 该函数如果定义了,将会被用作这个过滤器的自定义条件。其他所有的都会被忽略。"""
        q = Q()
        if self.title_list:
            titles = self.title_list.split(",")
            q = q & Q(title__in=titles)
        if self.title:
            q = q & Q(title=self.title)
        if self.pub_date:
            q = q & Q(pub_date=self.pub_date)
        if self.search:
            # sq = Q(title__icontains=self.search) | Q(pub_date__contains = Value(self.search, output_field=CharField()))
            sq = Q(title__icontains=self.search) | Q(pub_date__contains=self.search)
            q = q | sq
        return q

    def filter_title_list(self, value: str) -> Q:
        """自定义的过滤器函数,对传入的title_list字段转换成查询语句。
        title_list会使用','进行切割,生产过滤条件。"""
        if value:
            titles = value.split(",")
            return Q(title__in=titles)
        else:
            return Q()

@demo_api.get("/filter")
def events(request, filters: BookFilterSchema = Query(...)):  #
    books = Book.objects.all()
    print(filters.custom_expression())
    books = filters.filter(books)
    return ResponseSchema(data=books)

2.3 POST请求同时使用Path, Query, Body的示例

post请求可以包含Path,Query, Body等多个输入。下面的示例给出了继承Schema规整化这些输入。如果需要将相应的输入应用成过滤器,需要继承FilterSchema,编写相应的过滤方法。

python 复制代码
import datetime 

from ninja import NinjaAPI, Schema, UploadedFile, Form, File, Query, FilterSchema, Router, Path, Body


class DogSchema(Schema):
    # name: str
    dog_type: str
    age: int


class PathDate(Schema):
    year: int
    month: int
    day: int

    def value(self):
        return datetime.date(self.year, self.month, self.day)


@demo_api.post("/dog_mix_post/{year}/{month}/{day}")
def dog_mix_post(request, path: Path[PathDate], dog_item: DogSchema = Query(...), dog_item_body: DogSchema = Body(...)):
    """ name是路径参数;item是请求参数。"""
    return {"path": path.value(),
            "query": dog_item.dict(),
            "body": dog_item_body}
相关推荐
郑州光合科技余经理17 分钟前
本地生活服务系统:成品模块和定制接口怎么划界
java·前端·人工智能·后端·系统架构·php·ai编程
2603_9651481121 分钟前
家居百货蓝海:API挖掘高复购率生活小商品
大数据·服务器·人工智能·python·生活
阿童木写作3 小时前
跨境电商图片翻译工具推荐:批量图片翻译+视频字幕翻译+智能抠图
python·macos·音视频·xcode
cui_ruicheng4 小时前
LangChain 应用开发(十四):Agent 上下文与记忆机制
服务器·人工智能·python·langchain
circuitsosk4 小时前
任务规划器的三种范式对比:ReAct、Plan-and-Execute 与 Tree-of-Thought 在真实业务中的取舍
前端·javascript·python·react.js·llm·ai agent
shehuiyuelaiyuehao5 小时前
算法31,前缀和,可被k整除的子数组
数据结构·python·算法
宸津-代码粉碎机5 小时前
AI攻防战升级!基于Spring AI构建Java应用自动免疫安全体系
java·大数据·开发语言·人工智能·python·安全·spring
测试19985 小时前
如何用appium搭建Android自动化测试框架?
自动化测试·软件测试·python·测试工具·职场和发展·appium·测试用例
程序员大雄学编程5 小时前
微积分46. 无穷级数四大核心性质:从理论到实践的全方位解析
python·学习·微积分·学习工具
数字化转型分享点滴6 小时前
## 工厂数字化管理系统的价值体现:构建制造全流程数据闭环
python