Python 如何以较少的冗余/复制粘贴来编写此文件?

Python 如何以较少的冗余/复制粘贴来编写此文件?,python,django,django-views,Python,Django,Django Views,我通常不会以最好的方式编写Python代码,因为我对它比较陌生,有人要求我对Django应用程序进行更改,因为代码看起来不太好 下面是它的样子: @login_required def submission_set_rank(request): r1_obj_id = request.GET.get('rank1','') r2_obj_id = request.GET.get('rank2','') r3_obj_id = request.GET.get('ra

我通常不会以最好的方式编写Python代码,因为我对它比较陌生,有人要求我对Django应用程序进行更改,因为代码看起来不太好

下面是它的样子:

@login_required
def submission_set_rank(request):   

    r1_obj_id = request.GET.get('rank1','')
    r2_obj_id = request.GET.get('rank2','')
    r3_obj_id = request.GET.get('rank3','')
    r4_obj_id = request.GET.get('rank4','')
    r5_obj_id = request.GET.get('rank5','')

    #rate the first BallotStats object
    ballot_1 = BallotStats.objects.get(object_id=r1_obj_id)
    ballot_2 = BallotStats.objects.get(object_id=r2_obj_id)
    ballot_3 = BallotStats.objects.get(object_id=r3_obj_id)
    ballot_4 = BallotStats.objects.get(object_id=r4_obj_id)
    ballot_5 = BallotStats.objects.get(object_id=r5_obj_id)

    ballot_1.score += 5
    ballot_2.score += 4
    ballot_3.score += 3
    ballot_4.score += 2
    ballot_5.score += 1

    ballot_1.save()
    ballot_2.save()
    ballot_3.save()
    ballot_4.save()
    ballot_5.save()

    return HttpResponseRedirect('/submissions/results/film/')

事实证明,我意识到我一直都是这样编写Python代码的,有没有办法让它看起来更好,而不是占用21行以上的代码?

在你的例子中,一点循环都不会有什么坏处。事实上,一般来说,当你必须重复某件事两次以上时,试着让它成为一个循环

n = 5
for i in range(1, n+1):
    obj_id = request.GET('rank' + str(i), '')
    ballot = BallotStats.objects.get(object_id=obj_id)
    ballot.score += n - i + 1
    ballot.save()

最大的问题不是代码的风格,而是您要进行10次查询:5次用于获取对象,5次用于更新对象

立即使用以下命令筛选出对象:

这将最多进行6次查询:1次用于获取对象,5次用于更新对象

此外,您还可以使用decorator“标记”视图(这也适用于您)。它应当:

我有一种强烈的感觉,你甚至可以在一个更新查询中做到这一点。例如,在
executemany()的帮助下直接使用:


确保字段和表名正确。

如果我们讨论的是保存代码行,您可以将
.save()
替换为,并使用表达式来处理
+=
,从而将4行合并为一行。此外,正如@alecxe所讨论的,这将把您的查询减半。看起来是这样的:

@login_required
def submission_set_rank(request):
    BallotStats.objects.filter(object_id=request.GET.get('rank1','')).update(score=‌​F('score') + 5)
    BallotStats.objects.filter(object_id=request.GET.get('rank2','')).update(score=‌​F('score') + 4)
    BallotStats.objects.filter(object_id=request.GET.get('rank3','')).update(score=‌​F('score') + 3)
    BallotStats.objects.filter(object_id=request.GET.get('rank4','')).update(score=‌​F('score') + 2)
    BallotStats.objects.filter(object_id=request.GET.get('rank5','')).update(score=‌​F('score') + 1)

    return HttpResponseRedirect('/submissions/results/film/')

循环:)一点<代码>用于。。。在…
中不会伤害任何人bit@Carsten不同意-这不仅仅是关于代码样式以及它的大小和美观。这也是关于性能的。另外,它确实是django特有的。这应该是一个带有
modelcoocefield
s的
表单
,并且覆盖了
save()
方法。@alecxe好的。特别是在你的答案中有了额外的信息,这确实更适合这样做。为什么要显示一个
@transaction.commit_手动提交
示例,而不是一个使用更简单的内置程序的示例,你链接到的程序实际上会更快?5
.filter().update()
调用将进行5次查询。@pcoronel,因为它不是一个简单的更新。此处根据
对象id
值为字段设置不同的值。请告诉我您是否可以使用
update()
将其写下来。谢谢。使用表达式:
BallotStats.objects.filter(object_id=request.GET.GET('rank1','')).update(score=F('score')+5)
,其中5个会处理它,不需要dictmappings@pcoronel好的,谢谢。但我指的是一次
update()
。您的解决方案将使数据库命中5次。不过,是的,这也是一种选择。
@login_required
@transaction.commit_manually
def submission_set_rank(request):   
    keys = {'rank1': 5, 'rank2': 4, 'rank3': 3, 'rank4': 2, 'rank5': 1}
    ranks = [request.GET.get(key,'') for key in keys]
    for ballot in BallotStats.objects.filter(object_id__in=ranks):
        ballot.score += keys[ballot.object_id]
        ballot.save()
    transaction.commit()

    return HttpResponseRedirect('/submissions/results/film/')
@login_required
def submission_set_rank(request):   
    keys = {'rank1': 5, 'rank2': 4, 'rank3': 3, 'rank4': 2, 'rank5': 1}
    ranks = [{'score': request.GET.get(key,''), 'id': key} for key in keys]

    cursor = connection.cursor()
    cursor.executemany("""
        UPDATE
            ballot_stats
        SET
            score = score + %(score)s
        WHERE
            object_id = %(id)s
    """, ranks)

    return HttpResponseRedirect('/submissions/results/film/')
@login_required
def submission_set_rank(request):
    BallotStats.objects.filter(object_id=request.GET.get('rank1','')).update(score=‌​F('score') + 5)
    BallotStats.objects.filter(object_id=request.GET.get('rank2','')).update(score=‌​F('score') + 4)
    BallotStats.objects.filter(object_id=request.GET.get('rank3','')).update(score=‌​F('score') + 3)
    BallotStats.objects.filter(object_id=request.GET.get('rank4','')).update(score=‌​F('score') + 2)
    BallotStats.objects.filter(object_id=request.GET.get('rank5','')).update(score=‌​F('score') + 1)

    return HttpResponseRedirect('/submissions/results/film/')