Django风格:长期查询?

时间:2011-10-28 17:51:15

标签: 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')

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

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

    person = models.UzbekistaniCitizen.objects.\
                              filter(occupation__income__taxable__gte=40000).\
                              exclude(face__eyes__color=blue).\
                              order_by('height').\
                              select_related('siblings', 'children')
    
  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')
    

4 个答案:

答案 0 :(得分:30)

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

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

答案 1 :(得分:16)

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

from models import UzbekistaniCitizen

person = UzbekistanCitizen.objects ...

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

#uses myfilter
person = UzbekistaniCitizen.objects.myfilter(hair__color=brown,
                                            eye__color= blue,
                                            height__gt= 56,
                                            ...
                                            ...
                                            )

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

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

person = UzbekistaniCitizen.males.hair("brown").eyes("blue").income(50000)

这在很大程度上取决于您计划如何使用它,我不会仅仅为了缩短查询时间而设置自定义管理器。

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

django在examples

中使用了变体编号#3
Entry.objects.filter(
     headline__startswith='What'
).exclude(
     pub_date__gte=datetime.now()
).filter(
     pub_date__gte=datetime(2005, 1, 1)
)

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

  

包装长行的首选方法是使用Python的暗示   括号,括号和括号内的行继续。长线可以   通过在括号中包装表达式来分解多行。这些   应优先使用反斜杠进行续行。

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

答案 2 :(得分:11)

我不确定您是否出于说明目的而这样做,但根据您的示例,请移除对filter的所有额外调用,并且只有一个filter。当filter有很多论据时,我也倾向于使用一种字典,这种字典可以更自然地分布在各行中:

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

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

答案 3 :(得分:5)

我的风格很好

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

在这种风格中,最方便的是你不必手工缩进,每行缩进是4个空格。

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

person = UzbekistaniCitizen.objects.myfilter(hair__color=brown,
                                            eye__color= blue,
                                            height__gt= 56,
                                            ...
                                            ...
                                            )

我的风格还有其他便利:

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')
)

2.轻松调试,您可以轻松评论某些条件

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

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