【问题标题】:Nesting multiple 'for' loops嵌套多个“for”循环
【发布时间】:2015-10-15 11:00:03
【问题描述】:

我正在使用 Django 1.8.3 和 Python 3.4.3

我的应用程序开始变大,我有几个“for”循环来访问同一模型中的多个对象。虽然我是 Python 新手,但我猜想有一种更简化的方法来准备我的代码。请看下面的小sn-p。该模型是“day_of_week”,但我有几个对象的“for”循环。我还放了一个sn-p的模板代码,来一张全图。感谢您的帮助。

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>
    ...

【问题讨论】:

  • 您能否创建一个名为“initialize”(或类似名称)的函数,该函数接收您尝试迭代的内容以及任何其他变量,以便将重复代码缩减为单个环形?那有意义吗?编辑:下面的第一个答案对我来说看起来不错。我的建议是需要对同一个方法进行大量调用,但参数不同。
  • 感谢您的建议。在我开始实施解决方案之前,是否可以询问您是否可以为这个菜鸟提供一个使用不同参数的建议示例?谢谢。
  • 当然我会简单地尝试一个样本,但我警告你我也是一个菜鸟:)。

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


【解决方案1】:

这应该也是一样的:

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
    ...

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

【讨论】:

  • 这很好——摆脱所有额外的'for'语句非常好! - 谢谢!!周末愉快。
【解决方案2】:

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

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

等等...我希望这会有所帮助。请随时批评此解决方案,说明为什么它是好方法或坏方法!我还在学习和提高自己:)

【讨论】:

  • 感谢您抽出宝贵时间尝试并提供帮助。我选择了“hiro protagonist”的解决方案,因为它对我来说似乎更容易理解,尤其是在我还在整理这一切的时候:)再次感谢您,周末愉快。
  • 没问题!周末愉快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-15
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多