Django实现多条件查询数据库的多种方式

本文详细介绍了在Django中实现多条件查询数据库的各种方法,包括使用原生SQL的extra方法、Django ORM的简单筛选与Q方法、rest-framework的SearchFilter以及django-filter的高级查询。重点分析了django-filter的内部实现,它提供了强大的筛选功能,并支持Django的所有查询方式。最后提到了自定义筛选器和转换器,以应对特殊需求。
摘要由CSDN通过智能技术生成

简介

本文主要整理了Django支持的多种复杂条件筛选数据库数据集的方法,同时属于上篇推文的拓展版,感兴趣的大兄弟们可以戳进去看看:django多种查询筛选数据库方式_Sean_TS_Wang的博客-CSDN博客


目录

简介

目录

正文

一、使用原生SQL实现多条件筛选(extra)

二、Django ORM 实现多条件筛选

简单筛选

Q方法

三、rest-framework提供的SearchFilter

四、django-filter

五、自定义筛选方式

总结


正文

本质上来说所有的多条件筛选方式最终都会转化成SQL语句进行操作,但是Django提供了多种方式,简化对数据库筛选操作。

一、使用原生SQL实现多条件筛选(extra)

上篇推文提到几种方式使用原生SQL操作数据库,这次使用extra做例子讲解,实际上效果是差不多的。

from django.db import models

class user(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=5)
    age = models.IntegerField()

    class Meta:
        db_table='user'

class animal(model.Model):
    kind = models.CharField(primary_key=True, max_length=5)
    name = models.CharField(max_length=5)
    sex = models.BooleanField()

    class Meta:
        db_table='animal'



# select user.id,user.name,user.age from user, animal where user.name=animal and user.age>18
User = User.objects.all().extra(tables=['animal'], 
                                where=[
                                    'user.name = animal.name',
                                    'user.age > 18'
                                    ]
                                )

优点:支持多表筛选,同时更符合数据库查询,甚至可以使用数据库函数简化查询

缺点:老问题,SQL注入。如何防止SQL注入的方法在上篇推文里面有写,基本思路就是对传过来的参数不要直接拼接到SQL语句中 ,而是先经过自己的排序处理再安装在相应的位置。 


二、Django ORM 实现多条件筛选

简单筛选

基本筛选

from django.db import models
from django.core import serializers
from django.Response import JSONResponse

class user(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=5)
    age = models.IntegerField()

    class Meta:
        db_table='user'


def userView(request):
    queryset = user.objects.all()
    id = request.GET.get('id',None)
    name = request.GET.get('name',None)
    age = request.GET.get('age',None)
    
    if id:
        queryset = queryset.filter(id=id)
    if name:
        queryset = queryset.filter(name=name)
    if age:
        queryset = queryset.filter(age=age)
    queryset = serializers.serializer('json',queryset)
    return JSONResponse({'data':queryset})
        

        

这样每个字段都需要if判断一下,有些麻烦,可以写个循环省略一下,因此Django也提供了一种批量参数筛选的方式——字典筛选(SearchFilter)

def userView(request):
    queryset = user.objects.all()
    filter_fields = {}
    for field in user._meta.fields:
        param = request.GET.get(field.name, None)
        if param:
            filter_fields[field.name] = param
    queryset = queryset.filter(**filter_fields)
    queryset = serializers.serilizer('json',queryset)
    return JSONResponse({'data':queryset})

优点:使用简便,支持大部分的筛选要求

缺点:所有查询条件都是并列的,相当于SQL语句中的AND,想要实现其他查询方式,需要额外设置查询条件。

Q方法

针对上述简答筛选的缺点,Django提供了Q方法,使得查询条件变得更加灵活。下列方法添加了同一个字段的OR筛选,使用逗号隔开

from django.db.models import Q
from functools import reduce

def userView(request):
    queryset = user.objects.all()
    for field in user._meta.fields:
        params = request.GET.get(field.name, None)
        if params:
            params = params.split(',')
            filter_fields = [Q(**{field.name: param}) for param in params]  
            filter_field  = reduce(lambda x,y:x|y, filter_fields)     
            queryset = queryset.filter(filter_field)
    queryset = serializers.serializer('json',queryset)
    return JSONResponse({'data':queryset})

 优点:针对简单查询进行优化,可以对查询条件同时做与或非操作(简单查询只能同时做与和非操作)

缺点:暂时还没发现,好像是不能跨表查询,没试过跨表查询,所以不清楚,有大佬可以一起讨论一下


三、rest-framework提供的SearchFilter

上述两种方法都还是需要在视图层(view)&#x

  • 3
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Django中,我们可以使用多种方法进行数据查询。其中一种方法是使用变量来查询数据。例如,可以使用以下代码来查询指定system_id的数据: data = BaspSys.objects.raw('select * from basp_sys where system_id =" %s"' %system_id) 另一种常见的查询方法是使用model文件来创建对应的表结构。在Django项目启动时,会根据设置文件中的数据库配置连接数据库,并返回一个tuple或tuple_List类型的数据。我们可以通过以下步骤来进行数据查询: 1. 创建对应的model文件并定义表结构。 2. 在查询代码中使用适当的函数,例如objects.all()来查询所有数据,或者使用filter()函数来根据特定条件进行查询。例如:BaspSys.objects.all()或BaspSys.objects.filter(system_id=system_id) 这样,我们就可以通过Django的数据查询方法来获取我们需要的数据。希望这些信息对您有所帮助。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [django中查询数据库数据的多种方式](https://blog.csdn.net/bugua3542/article/details/126840555)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [在django项目中导出数据到excel文件并实现下载的功能](https://download.csdn.net/download/weixin_38717171/12854334)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值