为什么获取复杂聚合需要别名错误? [英] why getting Complex aggregates require an alias error?

查看:31
本文介绍了为什么获取复杂聚合需要别名错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Django上工作,我有两个模型gis订单,我正在计算每个gig订单的平均完成时间。

订单模型中,我有两个字段订单开始时间(我在卖方接受订单时发送)和订单完成时间(我在卖方发货时发送)。

但问题是,如果我在ORDERS表中有与某个作业相关的数据,并且我检索了该作业,则它工作得很好,但是如果我尝试检索没有订单的作业(在ORDERS表中,没有包含该项目/作业的记录/字段),则会出现以下错误

Complex aggregates require an alias

Models.py

class Gigs(models.Model):
    title = models.CharField(max_length=255)
    category = models.ForeignKey(Categories , on_delete=models.CASCADE)
    images = models.ImageField(blank=True, null = True, upload_to= upload_path)
    price = models.DecimalField(max_digits=6, decimal_places=2)
    details = models.TextField()
    seller = models.ForeignKey(User,default=None, on_delete=models.CASCADE)
    
    @property
    def average_completionTime(self):
        if getattr(self, '_average_completionTime', None):
            return self._average_completionTime
        return self.gig.aggregate(Avg(F('orderCompletedTime') - F('orderStartTime')))

class Orders(models.Model):
    buyer = models.ForeignKey(User,default=None, on_delete=models.CASCADE,related_name='buyer_id')
    seller = models.ForeignKey(User,default=None, on_delete=models.CASCADE,related_name='seller_id')
    item = models.ForeignKey(Gigs,default=None, on_delete=models.CASCADE,related_name='gig')
    payment_method= models.CharField(max_length=10)
    address = models.CharField(max_length=255)
    mobile = models.CharField(max_length=13,default=None)
    quantity = models.SmallIntegerField(default=1)
    status = models.CharField(max_length=13,default='new order')
    orderStartTime = models.DateTimeField(default=timezone.now)
    orderCompletedTime = models.DateTimeField(default=timezone.now)
    isCompleted = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

Views.py

class RetrieveGigsAPI(GenericAPIView, RetrieveModelMixin):
    def get_queryset(self):
        return Gigs.objects.annotate(
            _average_completionTime=Avg(
                ExpressionWrapper(F('gig__orderCompletedTime') - F('gig__orderStartTime'), output_field=DurationField()),
                filter=Q(gig__isCompleted=True),
            )
        )
    serializer_class = GigsSerializerWithAvgTime
    permission_classes = (AllowAny,)

    def get(self, request , *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

Serializers.py

class GigsSerializerWithAvgTime(serializers.ModelSerializer):
    average_completionTime = serializers.SerializerMethodField()
    def get_average_completionTime(self, obj):
        return obj.average_completionTime
    class Meta:
        model = Gigs
        fields = ['id','title','category','price','details','seller','images','average_completionTime']

示例

例如,如果我们在Orders表中有以下数据,其中Item是来自GIGS表的外键 现在,如果我检索gig 22,它工作正常,并提供Api中的所有字段,包括平均完成时间,但如果我想获取gig 23或任何其他字段,则会出现错误

但我希望它返回所有其他字段相同的平均完成时间:空

完全错误跟踪

Environment:


Request Method: GET
Request URL: http://localhost:8000/seller/GigApi/23/

Django Version: 3.0.11
Python Version: 3.9.1
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'rest_framework',
 'djoser',
 'accounts',
 'adminuser',
 'seller',
 'buyer',
 'corsheaders']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.middleware.common.CommonMiddleware']



Traceback (most recent call last):
  File "C:Python39libsite-packagesdjangodbmodelsquery.py", line 374, in aggregate
    arg.default_alias
  File "C:Python39libsite-packagesdjangodbmodelsaggregates.py", line 65, in default_alias
    raise TypeError("Complex expressions require an alias")

During handling of the above exception (Complex expressions require an alias), another exception occurred:
  File "C:Python39libsite-packagesdjangocorehandlersexception.py", line 34, in inner
    response = get_response(request)
  File "C:Python39libsite-packagesdjangocorehandlersase.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:Python39libsite-packagesdjangocorehandlersase.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:Python39libsite-packagesdjangoviewsdecoratorscsrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:Python39libsite-packagesdjangoviewsgenericase.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:Python39libsite-packages
est_frameworkviews.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "C:Python39libsite-packages
est_frameworkviews.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:Python39libsite-packages
est_frameworkviews.py", line 480, in raise_uncaught_exception
    raise exc
  File "C:Python39libsite-packages
est_frameworkviews.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "C:FYPackendsellerviews.py", line 76, in get
    return self.retrieve(request, *args, **kwargs)
  File "C:Python39libsite-packages
est_frameworkmixins.py", line 56, in retrieve
    return Response(serializer.data)
  File "C:Python39libsite-packages
est_frameworkserializers.py", line 548, in data
    ret = super().data
  File "C:Python39libsite-packages
est_frameworkserializers.py", line 246, in data
    self._data = self.to_representation(self.instance)
  File "C:Python39libsite-packages
est_frameworkserializers.py", line 515, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "C:Python39libsite-packages
est_frameworkfields.py", line 1870, in to_representation
    return method(value)
  File "C:FYPackendsellerserializers.py", line 21, in get_average_completionTime
    return obj.average_completionTime
  File "C:FYPackendsellermodels.py", line 29, in average_completionTime
    return self.gig.aggregate(Avg(F('orderCompletedTime') - F('orderStartTime')))
  File "C:Python39libsite-packagesdjangodbmodelsmanager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:Python39libsite-packagesdjangodbmodelsquery.py", line 376, in aggregate
    raise TypeError("Complex aggregates require an alias")

Exception Type: TypeError at /seller/GigApi/23/
Exception Value: Complex aggregates require an alias

推荐答案

正如@Iain Shelvington提到的,您可以这样为聚合设置名称以解决错误:

return self.gig.aggregate(average_completion=Avg(F('orderCompletedTime') - F('orderStartTime')))['average_completion']
                          # ^^^ Add this

此外,由于在get_queryset中它可能已经具有计算值,您可以尝试将getattr更改为hasattr,然后只返回:

    @property
    def average_completionTime(self):
        if hasattr(self, '_average_completionTime'):
            return self._average_completionTime

        return self.gig.aggregate(
            average_completion=Avg(F('orderCompletedTime') - F('orderStartTime'))
        )['average_completion']

这是为了检查GIG实例是否已经计算了_average_completionTime,以防止再次计算。

这篇关于为什么获取复杂聚合需要别名错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆