为了账号安全,请及时绑定邮箱和手机立即绑定

Django:按值过滤或返回所有记录

Django:按值过滤或返回所有记录

小唯快跑啊 2021-03-28 15:47:07
我有以下代码(django,python):def function(self, some_id):    if some_id:        return Model1.objects.filter(model2__id=some_id)    else:        return Model1.objects.all()我想知道是否可以使用单个return语句来重构此代码?Model1在Model2.id上具有外键。
查看完整描述

2 回答

?
蛊毒传说

TA贡献1895条经验 获得超3个赞

def function(self, some_id):

    filter_kwargs = {}


    if some_id:

        filter_kwargs['model2__id'] = some_id


    return Model1.objects.filter(**filter_kwargs)

应该可以满足您的问题,尽管我会说书面形式最有可能。


查看完整回答
反对 回复 2021-04-09
?
子衿沉夜

TA贡献1828条经验 获得超3个赞

好吧,您可以像这样解决此问题:


def function(self, some_id):

    return Model1.objects.filter(*(some_id and [Q(model2__id=some_id)] or []))

但这是很神秘的。


我个人很喜欢实现一个filter_not_none,它只是过滤掉带有Noneas值的语句,例如:


def filter_not_none(qs, **kwargs):

    return qs.filter(**{k: v for k, v in kwargs.item() if v is not None})

然后我们可以简单地使用:


def function(self, some_id):

    return filter_not_none(Model1.objects, model2__id=some_id)

这适用于任意数量的命名参数。因此不是位置参数或Q对象。


这是有效的,因为filter(..)没有参数的a不会过滤任何内容。我们使用字典理解,从而检查哪个kwargs具有非None值,并且仅将它们传递给.filter(..)调用。


然后,您可以使用例如:


return filter_not_none(

    Model.objects,

    name=some_name,

    date__lt=some_date

)

如果some_name是None,我们做的名字没有过滤器,如果some_date是None我们没有过滤器时date__lt,如果两者都是None,我们不会过滤所有,并且如果两者都没有 None,我们过滤器上都。


我们可以对其进行扩展以使其也可以与Q对象一起使用*args,但是检查这些-Q对象和表达式将非常困难,并且还可能导致各种不良行为。但是,也需要Q对象的扩展是:


def filter_not_none(qs, *args, **kwargs):

    # warning, does not perform manipulations on Q-objects, Q-expressions

    # and unnamed parameters in general

    return qs.filter(

        *args,

        **{k: v for k, v in kwargs.item() if v is not None}

    )


查看完整回答
反对 回复 2021-04-09
  • 2 回答
  • 0 关注
  • 283 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信