为什么获取复杂聚合需要别名错误? [英] why getting Complex aggregates require an alias error?
本文介绍了为什么获取复杂聚合需要别名错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我在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屋!
查看全文