【问题标题】:Multiple For Loops Django多个 For 循环 Django
【发布时间】:2021-09-17 14:28:19
【问题描述】:

我有以下两个模型 ASPBoookings 和 Athlete。运动员模型通过名为运动员的外键链接到 ASPBookings 模型。

我正在尝试创建一个循环,循环遍历 ASPBooking 表中的所有预订,并找出每个运动员最近的预订(该表可以包含多个预订,每个预订都针对相同或不同的运动员(athlete_id )。

获得此信息(booking_date 和运动员 ID)后,我希望能够自动更新运动员模型中的“最新 ASP 会话字段”。

这是我迄今为止尝试过的。我可以循环浏览 ASPBookings 表中的预订,并使用 booking_date 和运动员 ID 检索和更新“最新的 ASP 会话字段”,但我不能对表中的多个不同运动员执行此操作。目前,该视图仅识别最新的预订和分配的运动员 ID,然后更新该字段。

提前感谢您的帮助。

下面是代码:

ASPBookings 模型

class ASPBookings(models.Model):
    asp_booking_ref = models.CharField(max_length=10, default=1)
    program_type = models.CharField(max_length=120, default='asp')
    booking_date = models.DateField()
    booking_time = models.CharField(max_length=10, choices=booking_times)
    duration = models.CharField(max_length=10, choices=durations, default='0.5')
    street = models.CharField(max_length=120)
    suburb = models.CharField(max_length=120)
    region = models.CharField(max_length=120, choices=regions, default='Metro')
    post_code = models.CharField(max_length=40)
    organisation_type = models.CharField(max_length=120,choices=organisation_types, default='Government School')
    audience_number = models.CharField(max_length=10)
    presentation_form = models.CharField(max_length=120, choices=presentation_form_options, default='Face to Face')
    contact_name = models.CharField(max_length=80)
    email = models.EmailField()
    phone_number = models.CharField(max_length=120)
    comments = models.TextField()
    status = models.CharField(max_length=80, choices=statuses, default='TBC')
    email_sent = models.BooleanField(default=False)
    athlete = models.ForeignKey(Athlete, default= '1', on_delete=models.CASCADE)

    def __str__(self):
        return self.contact_name
        
    # return URL after the POST has been submitted.
    def get_absolute_url(self):
        return reverse('vistours:success')

运动员模特

class Athlete(models.Model):
    athlete_ref = models.CharField(max_length=10, default=1)
    athlete_name = models.CharField(max_length=80)
    email = models.EmailField()
    phone_number = models.CharField(max_length=120)
    home = models.CharField(max_length=120)
    education = models.CharField(max_length=120)
    sport = models.CharField(max_length=120, choices=sports, default='1500m Runner')
    notes = models.TextField(default='None')
    gender = models.CharField(max_length=120, choices=genders, default='Not Specified')
    para_athlete = models.BooleanField(blank=True)
    working_with_children = models.BooleanField(blank=True)
    expiry_date = models.DateField(blank=True, null=True)
    available = models.BooleanField(blank=True)
    available_from = models.DateField(blank=True, null=True)
    bfbw = models.BooleanField(blank=True)
    latest_bfbw_session = models.DateField(blank=True, null=True)
    number_bfbw_sessions = models.CharField(blank=True, null=True, max_length=10)
    asp = models.BooleanField(blank=True)
    latest_asp_session = models.DateField(blank=True, null=True)
    number_asp_sessions = models.CharField(blank=True, null=True, max_length=10)
    tours = models.BooleanField(blank=True)
    latest_tours_session = models.DateField(blank=True, null=True)
    number_tours_sessions = models.CharField(blank=True, null=True, max_length=10)

    def __str__(self):
        return self.athlete_name

    # return URL after the POST has been submitted.
    def get_absolute_url(self):
        return reverse('home')

查看

# Complete first loop for inital values.
    for date in asp_data:
        if date.booking_date != None:
            first_loop = date.booking_date
            athl_id = date.athlete_id
            break
    # If next value is greater than inital value, replace current values.      
    for date in asp_data:
        if date.booking_date != None:
            if date.booking_date > first_loop:
                first_loop = date.booking_date
                athl_id = date.athlete_id
    

    print(first_loop)
    print(athl_id)

    update_date = Athlete.objects.get(id=athl_id)
    update_date.latest_asp_session = first_loop
    update_date.save()

【问题讨论】:

    标签: python django django-models django-views django-queryset


    【解决方案1】:

    不需要循环。您可以使用子查询一次性为所有运动员执行此操作,将所有繁重的工作留给您的数据库:

    from django.db.models import F, OuterRef, Subquery
    
    bookings = ASPBookings.objects.filter(
        athlete=OuterRef('pk')
    ).order_by('-booking_date')
    
    Athlete.objects.annotate(
        latest_asp_booking_date=Subquery(
            bookings.values('booking_date')[:1]
        )
    ).update(
        latest_asp_session=F('latest_asp_booking_date')
    )
    

    【讨论】:

    • 感谢 bdbd,我需要更多学习子查询。这看起来比我尝试做的要清楚得多。
    猜你喜欢
    • 1970-01-01
    • 2015-03-10
    • 2012-09-26
    • 1970-01-01
    • 2019-03-09
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 2016-05-24
    相关资源
    最近更新 更多