嵌套多个' for'循环

时间:2015-07-24 17:09:21

标签: django python-3.x django-models django-templates django-views

我正在使用Django 1.8.3和Python 3.4.3

我的应用程序开始变大,我有几个' for'循环访问同一模型中的多个对象。虽然我是Python的新手,但我猜测有一种更简化的方法来准备我的代码。请参阅下面的小片段。该模型是'day_of_week'但我有一个' for'循环几个对象。我还放置了一个模板代码片段,以获得完整的图片。谢谢你的帮助。

views.py

def get_context_data(self, **kwargs):
        context = super(EmailListView, self).get_context_data(**kwargs)
        days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
        months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October',
                  'November', 'December']
        subject_type = ['Offer', 'Sell', 'Fear', 'Learn']
        content_type = ['Offer', 'Sell', 'Fear', 'Learn']
        email_list = ['FMGB', 'FMGR', 'AE', 'IBA']

        total_campaigns = {}
        total_campaigns_month = {}
        total_recipients = {}
        total_unsubscribes = {}
        total_bounces = {}
        total_open = {}
        total_clicks = {}

        for day in days:
            total_campaigns[day] = Email.objects.filter(day_of_week=day).count()
        for recipients in days:
            total_recipients[recipients] = Email.objects.filter(day_of_week=recipients).aggregate(
                Sum('recipients')).get('recipients__sum', 0.00)
        for unsubscribes in days:
            total_unsubscribes[unsubscribes] = Email.objects.filter(day_of_week=unsubscribes).aggregate(
                Sum('unsubscribes')).get('unsubscribes__sum', 0.00)
        for bounces in days:
            total_bounces[bounces] = Email.objects.filter(day_of_week=bounces).aggregate(Sum('bounces')).get(
                'bounces__sum', 0.00)
        for open in days:
            total_open[open] = Email.objects.filter(day_of_week=open).aggregate(
                Sum('open')).get('open__sum', 0.00)
        for clicks in days:
            total_clicks[clicks] = Email.objects.filter(day_of_week=clicks).aggregate(
                Sum('clicks')).get('clicks__sum', 0.00)

模板代码段...(email.html)

{% if email_list %}
    <tr>
       <td>Monday</td>
       <td>{{ total_campaigns.Monday }}</td>
       <td>{{ total_recipients.Monday }}</td>
       <td>{{ total_unsubscribes.Monday  }}</td>
       <td>{{ total_bounces.Monday  }}</td>
       <td>{{ total_open.Monday  }}</td>
       <td>{{ total_clicks.Monday  }}</td>
       <td>{% average total_open.Monday total_recipients.Monday %}</td>
       <td>{% average total_clicks.Monday total_open.Monday %}</td>
    </tr>
    ...

2 个答案:

答案 0 :(得分:3)

这应该是一样的:

for day in days:
    total_campaigns[day] = Email.objects.filter(day_of_week=day).count()
    # recipients
    total_recipients[day] = Email.objects.filter(day_of_week=day).aggregate(
        Sum('recipients')).get('recipients__sum', 0.00)
    # unsubscribes
    total_unsubscribes[day] = Email.objects.filter(day_of_week=day).aggregate(
        Sum('unsubscribes')).get('unsubscribes__sum', 0.00)
    # bounces
    total_bounces[day] = Email.objects.filter(day_of_week=day).aggregate(
        Sum('bounces')).get('bounces__sum', 0.00)
    # open
    total_open[day] = Email.objects.filter(day_of_week=day).aggregate(
        Sum('open')).get('open__sum', 0.00)
    # clicks
    total_clicks[day] = Email.objects.filter(day_of_week=day).aggregate(
        Sum('clicks')).get('clicks__sum', 0.00)

并且我对django ORM并不过分熟悉,但您可以使用

来减少数据库查询的数量
for day in days:
    day_objects = Email.objects.filter(day_of_week=day)
    total_campaigns[day] = day_objects.count()
    # recipients
    ...

... etc(并将所有Email.objects.filter(day_of_week=day)替换为新定义的day_objects

答案 1 :(得分:0)

所以我不完全确定这是否是正确的语法,但也许您可以尝试这种方法?

def initialize_dict(dict, days, dict_name):
    for day in days:
        if dict_name='':
            dict[day] = Email.objects.filter(day_of_week=day).count()
        else:
            dict[day] = Email.objects.filter(day_of_week=day)
                       .aggregate(Sum(dict_name))
                       .get(dict_name + '__sum', 0.00)

我不确定这是否是更好的解决方案,但它是另一种选择。您可以决定将日期设为全局变量,而不必将其传递给函数。几个示例调用将是:

initialize_dict(total_campaigns, days, '')
initialize_dict(total_recipients, days, 'recipients')

依此类推......我希望这会有所帮助。请随意批评这个解决方案为什么它是一个好的或坏的方法!我仍在学习和提高自己:)