Django风格:长期查询?

spe*_*son 21 django coding-style

我有一些相当长(~150个字符)的django查询.将它们分成多行的首选方法是什么?

例如(不,不是我的真实代码):

编辑:更改了示例,因为人们专注于重复过滤,而不是查询的长度:

person = models.UzbekistaniCitizen.objects.filter(occupation__income__taxable__gte=40000).exclude(face__eyes__color=blue).order_by('height').select_related('siblings', 'children')
Run Code Online (Sandbox Code Playgroud)

以下是我能想到的两种方式:

  1. 使用反斜杠作为换行符:

    person = models.UzbekistaniCitizen.objects.\
                              filter(occupation__income__taxable__gte=40000).\
                              exclude(face__eyes__color=blue).\
                              order_by('height').\
                              select_related('siblings', 'children')
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在新行中重新应用过滤器:

    person = models.UzbekistaniCitizen.objects
    person = person.(occupation__income__taxable__gte=40000)
    person = person.exclude(face__eyes__color=blue)
    person = person.order_by('height')
    person = person.select_related('siblings', 'children')
    
    Run Code Online (Sandbox Code Playgroud)

Sea*_*ean 32

您可以在整个rhs周围使用括号来获得隐含的行继续:

person = (models.UzbekistaniCitizen
                .objects
                .filter(occupation__income__taxable__gte=40000)
                .exclude(face__eyes__color=blue)
                .order_by('height')
                .select_related('siblings', 'children'))
Run Code Online (Sandbox Code Playgroud)

  • 到目前为止,这是最易读的。我刚刚在一些开源代码中看到了这一点。我不敢相信我多年来一直在编写python而不知道这一点。这个语法有什么缺点吗? (2认同)
  • 不,一点都没有。我避免了一段时间,因为我担心它会被解释为元组定义。在实践中,这是毫无根据的恐惧,一个单元元组defs必须具有尾随逗号的原因变得更加清楚:(1,)而不是(1)。 (2认同)

ash*_*ods 16

突然出现在我眼中的第一件事是,在这种情况下导入Class更常见,而不是模块:

from models import UzbekistaniCitizen

person = UzbekistanCitizen.objects ...
Run Code Online (Sandbox Code Playgroud)

根据您是否经常使用此类过滤,您可以考虑制作自己的自定义模型管理器,以便采用以下形式:

#uses myfilter
person = UzbekistaniCitizen.objects.myfilter(hair__color=brown,
                                            eye__color= blue,
                                            height__gt= 56,
                                            ...
                                            ...
                                            )
Run Code Online (Sandbox Code Playgroud)

或者在您的情况下可能更方便的任何其他内容.

注意:编辑后,使用经理仍然适用.myfilter的方法不必模拟过滤器功能,而管理员可以做更多的事情:

person = UzbekistaniCitizen.males.hair("brown").eyes("blue").income(50000)
Run Code Online (Sandbox Code Playgroud)

这在很大程度上取决于您计划如何使用它,我不会只是为了保持查询更短而自定义管理器.

在您上面提到的两个选项之间,我更喜欢变体#1.我个人认为它更具可读性,一目了然我知道发生了什么.#2只是让位于很多人的方式,我的眼睛需要做更多的工作才能找到被调用的相关方法来了解实际发生的事情.

django在示例中使用了变体编号#3 :

Entry.objects.filter(
     headline__startswith='What'
).exclude(
     pub_date__gte=datetime.now()
).filter(
     pub_date__gte=datetime(2005, 1, 1)
)
Run Code Online (Sandbox Code Playgroud)

虽然#3 符合PEP 8 ......

包装长行的首选方法是在括号,括号和括号内使用Python隐含的行继续.通过将表达式包装在括号中,可以在多行中分割长行.这些应该优先使用反斜杠来继续行.

...我个人不喜欢在python中使用像这样的悬挂括号,但是随着风格决定的出现:使用你觉得更舒服的东西,只要它是可读和一致的.

  • 请参阅Sean的答案,以使用隐含的行连续性更清晰的方法http://stackoverflow.com/a/34335578/1026333 (2认同)

Chr*_*att 11

我不确定你是否出于说明目的而做,但根据你的例子,删除所有额外的调用,filter只有一个filter.当a有很多论据时filter,我也倾向于使用一个字典,它可以更自然地跨行:

person = UzbekistaniCitizen.objects.filter(**{
    'hair__color': 'brown',
    'eye__color': 'blue',
    'height__gt': 56,
    'age__lte': 30,
    'job__income__taxable__gt': 40000,
}).select_related()
Run Code Online (Sandbox Code Playgroud)

FWIW:如果您需要动态修改a的参数,这也是一个方便的方法filter.只需创建参数字典,您就可以根据代码中的逻辑在字典中追加/更改/删除项目.然后,你最终用它来filter:MyModel.objects.filter(**my_dict)


Lee*_*Lee 5

我的风格很好

person = (
    models
    .UzbekistaniCitizen
    .objects
    .filter(occupation__income__taxable__gte=40000)
    .exclude(face__eyes__color=blue)
    .order_by('height')
    .select_related('siblings', 'children')
)
Run Code Online (Sandbox Code Playgroud)

在这种样式中,最方便的是您不必手动缩进,每行缩进是四个空格。

以下缺点:1.如果重命名可变人,则必须手动调整缩进量。2.如果您的型号名称很长,很难限制每行少于80个字符。

person = UzbekistaniCitizen.objects.myfilter(hair__color=brown,
                                            eye__color= blue,
                                            height__gt= 56,
                                            ...
                                            ...
                                            )
Run Code Online (Sandbox Code Playgroud)

我的风格还有其他便利:

1.可以添加评论:

person = (
    models
    .UzbekistaniCitizen
    .objects
    .filter(occupation__income__taxable__gte=40000)  # your comment
    .exclude(face__eyes__color=blue)
    .order_by('height')  # 2016-10-11 add
    .select_related('siblings', 'children')
)
Run Code Online (Sandbox Code Playgroud)

2.轻松调试,您可以轻松注释一些条件

下面的代码可以正常工作。这在调试中非常有用,您可以逐行注释条件,而不是删除并重做。

person = (
    models
    .UzbekistaniCitizen
    .objects
    # .filter(occupation__income__taxable__gte=40000)
    .exclude(face__eyes__color=blue)
    # .order_by('height')
    .select_related('siblings', 'children')
)
Run Code Online (Sandbox Code Playgroud)