【问题标题】:Django Queries Count and updateDjango 查询计数和更新
【发布时间】:2023-03-31 16:12:01
【问题描述】:

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

我最近看到了带有 Views 的查询/子查询,我一直在尝试使用它们(仍在学习)来提供 ASPBookings 表中分配给每个运动员的所有预订的计数。获得信息后,我需要运动员模型中的“number_of_asp_sessions”随着每个运动员的预订计数自动更新。

例如运动员 ID 1,可能分配了两个预订。运动员 ID 2,可能分配了一个预订。 number_of_asp_sessions 应该显示每个运动员的这些数字。

希望这是有道理的,并感谢您提前提供任何帮助。欣赏它。

下面是代码:

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

查看

def count_bookings(request):

    Athlete.objects.annotate(number_of_asp_sessions=Count('aspbookings')).update(number_asp_sessions=F('number_of_asp_sessions'))
    return HttpResponseRedirect(request.META.get('HTTP_REFERER'))

【问题讨论】:

  • expiry_date 是什么?

标签: django django-models group-by count django-queryset


【解决方案1】:

试试下面:

Athlete.objects.annotate(number_of_asp_sessions=Count('aspbookings')).update(number_asp_sessions=F('number_of_asp_sessions')

这将计算每位运动员的所有 asp 预订,然后根据所有运动员的注释字段一次性更新 number_asp_sessions 字段。

编辑:

我试过了,不知怎的,我得到了:

    FieldError: Aggregate functions are not allowed in this query

似乎我无法使用带注释的字段进行更新。现在这应该可以工作:

objs = []
for a in Athlete.objects.annotate(number_of_asp_sessions=Count('aspbookings')):
    a.number_asp_sessions = a.number_of_asp_sessions
    objs.append(a)
Athlete.objects.bulk_update(objs, ['number_asp_sessions'])

编辑:

最终使用子查询;)这也应该有效:

Athlete.objects.update(
     number_asp_sessions=Subquery(
          Athlete.objects.annotate(number_of_asp_sessions=Count('aspbookings')).filter(pk=OuterRef('pk')).values('number_of_asp_sessions')[:1]
     )
)

【讨论】:

  • 有一个错字:Count('aspbookings_set') 因为反向关系的名字没有重新定义
  • 感谢 bdbd 和 Raphael,我在 def count_bookings(request) 上尝试了您的评论:Athlete.objects.annotate(number_of_asp_sessions=Count('aspbookings_set')).update(number_asp_sessions=F('number_of_asp_sessions') ) 返回 HttpResponseRedirect(request.META.get('HTTP_REFERER')) 但我收到以下错误。 /admin_bookings/athletes/all/ 的 FieldError 无法将关键字“aspbookings_set”解析为字段。
  • 完全错误。无法将关键字“aspbookings_set”解析为字段。选项有:asp、aspbookings、运动员姓名、运动员参考、available、a​​vailable_from、bfbw、bfbwbookings、教育、电子邮件、expiry_date、性别、家庭、id、latest_asp_session、latest_bfbw_session、latest_tours_session、notes、number_asp_sessions、number_bfbw_sessions、number_tours_sessions、para_athlete、phone_number、schooltourbookings ,运动,旅游,与孩子一起工作
  • 不,我收到一条不同的消息“此查询中不允许加入字段引用”
  • 当您昨天在另一个查询中帮助我时,您使用 OuterRef 来引用主键,我们是否需要在查询中添加类似的内容。这是来自昨天的查询 asp_bookings = ASPBookings.objects.filter(athlete=OuterRef('pk') ).order_by('-booking_date')
【解决方案2】:

我认为你需要注释一次。

ASPBookings.objects.annotate(num_athletes=Count('program_type'))

【讨论】:

  • 感谢 Daniel,虽然这不会引发错误,但它不允许我更新字段“number_asp_sessions”。我尝试将更新添加到您的代码 ASPBookings.objects.annotate(num_athletes=Count('program_type')).update(number_asp_sessions=F('num_athletes')) 但随后我收到类似的消息错误,上面说字段名称 'number_asp_sessions ' 不存在。
【解决方案3】:

您不需要字段number_asp_sessions。 您正在寻找的是从Athlete 访问与ASPBookings 的反向关系

你可以简单地给模型添加一个方法Athlete

class Athlete(models.Model):
    athlete_ref = models.CharField(max_length=10, default=1)
    ...
    ...
    def get_number_of_sessions(self):
        return self.aspbookings_set.all().count()

aspbookings_set 指从 Athlete 类的实例查看的类 ASPBookings 的 ForeignKey 引用实例

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-23
    • 2011-01-29
    • 2011-09-01
    • 2019-09-11
    • 1970-01-01
    • 2020-05-20
    • 2020-02-12
    • 1970-01-01
    相关资源
    最近更新 更多