Django 在搜索表单中同时注释 Sum 和 Min/Max
Django Annotate With Sum And Min/Max At The Same Time In Search Form
我有一个课程页面,它是课程搜索表单的搜索结果。在下面的当前代码中,它目前允许用户输入最小和最大视图以及包含该课程 "views" 标准的 return 课程。
本应在课程 "views" field/column
中,但在课程 "views" field/column 中错误地执行了此操作
我想注释(或子查询?)所有课程视图的总和,但要确保用户能够找到课程视图符合其 min/max 搜索条件的所有课程?换句话说,让用户能够通过搜索表单过滤和搜索具有 X 最小和 Y 最大视图之间的课程视图的课程以及 return 所有具有该标准的课程。或者仅按仅具有 X 最小观看次数或仅 Y 最大观看次数的课程进行搜索。
获取课程中所有课程视图总和的有效注释:
Course.objects.annotate(foobar=Sum("lesson__views")).order_by("foobar")
尝试过:
if min_views_query:
qs = Course.objects.annotate(foobar=Sum(Min("lesson__views"))).order_by("foobar")
if max_views_query:
qs = Course.objects.annotate(foobar=Sum(Max("lesson__views"))).order_by("foobar")
错误:
django.core.exceptions.FieldError:无法计算 Min('Sum'):'Sum' 是一个聚合
代码:
Courses Forms.py:
class CourseForm(forms.Form):
min_views = forms.IntegerField(widget=forms.NumberInput(attrs={'class':'form-control', 'autocomplete':'off','id':'min_views', 'type':'number', 'min':'0', 'placeholder': '0'}), required=False, validators=[MinValueValidator(0), MaxValueValidator(99999999999999999999999999999999999)])
max_views = forms.IntegerField(widget=forms.NumberInput(attrs={'class':'form-control', 'autocomplete':'off', 'id':'max_views', 'type':'number', 'min':'0', 'placeholder': '1000000'}), required=False, validators=[MinValueValidator(0), MaxValueValidator(99999999999999999999999999999999999)])
def __init__(self, *args, **kwargs):
super(CourseForm, self).__init__(*args, **kwargs)
self.fields['min_views'].label = "Min Views:"
self.fields['max_views'].label = "Max Views:"
Courses Views.py:
class CourseListView(ListView):
model = Course
def get_queryset(self):
qs = super().get_queryset()
self.form = form = CourseForm(self.request.GET)
if form.is_valid():
min_views_query = self.request.GET.get('min_views')
max_views_query = self.request.GET.get('max_views')
if min_views_query:
qs = qs.filter(views__gte=min_views_query)
if max_views_query:
qs = qs.filter(views__lte=max_views_query)
return qs
Courses Models.py:
class Course(models.Model):
views = models.PositiveIntegerField(default=0)
@property
def total_lesson_views(self):
lessons_dictionary = Lesson.objects.filter(course=self).aggregate(Sum('views'))
return lessons_dictionary['views__sum']
class Lesson(models.Model):
course = models.ForeignKey(Course, on_delete=models.SET_NULL, null=True)
views = models.PositiveIntegerField(default=0)
如果我没理解错的话,你需要这个:
qs = Course.objects.annotate(Min("lesson__views"), Max("lesson_views")).\
aggregate(Sum("lesson__views__min"), Sum("lesson__views__max"))
该查询集应包含两个字段:lesson__views__min__sum
和 lesson__views__max__sum
,您可以使用它们进行过滤。
如果您的 Lesson
模型中已经有 views
,您可以从 Course
模型中过滤 Lessons
:
qs = Course.objects.filter(lesson__views__lt=top_limit,
lesson__views__gt=bottom__limit).\
distinct()
这会根据 个人 的观看次数选择 Lesson
,即回答 "Give me all Courses which includes at least one Lesson with its views between X and Y"。
如果您需要聚合所有 Lesson
视图然后过滤:
qs = Course.objects.annotate(Sum("lesson__views")).filter(
lesson__views__sum__lt=top_limit,
lesson__views__sum__gt=bottom_limit)
这回答了问题 "Give me all Courses which the Sum of all the views of its Lessons combined are between X and Y"。
我有一个课程页面,它是课程搜索表单的搜索结果。在下面的当前代码中,它目前允许用户输入最小和最大视图以及包含该课程 "views" 标准的 return 课程。
本应在课程 "views" field/column
中,但在课程 "views" field/column 中错误地执行了此操作我想注释(或子查询?)所有课程视图的总和,但要确保用户能够找到课程视图符合其 min/max 搜索条件的所有课程?换句话说,让用户能够通过搜索表单过滤和搜索具有 X 最小和 Y 最大视图之间的课程视图的课程以及 return 所有具有该标准的课程。或者仅按仅具有 X 最小观看次数或仅 Y 最大观看次数的课程进行搜索。
获取课程中所有课程视图总和的有效注释:
Course.objects.annotate(foobar=Sum("lesson__views")).order_by("foobar")
尝试过:
if min_views_query:
qs = Course.objects.annotate(foobar=Sum(Min("lesson__views"))).order_by("foobar")
if max_views_query:
qs = Course.objects.annotate(foobar=Sum(Max("lesson__views"))).order_by("foobar")
错误: django.core.exceptions.FieldError:无法计算 Min('Sum'):'Sum' 是一个聚合
代码:
Courses Forms.py:
class CourseForm(forms.Form):
min_views = forms.IntegerField(widget=forms.NumberInput(attrs={'class':'form-control', 'autocomplete':'off','id':'min_views', 'type':'number', 'min':'0', 'placeholder': '0'}), required=False, validators=[MinValueValidator(0), MaxValueValidator(99999999999999999999999999999999999)])
max_views = forms.IntegerField(widget=forms.NumberInput(attrs={'class':'form-control', 'autocomplete':'off', 'id':'max_views', 'type':'number', 'min':'0', 'placeholder': '1000000'}), required=False, validators=[MinValueValidator(0), MaxValueValidator(99999999999999999999999999999999999)])
def __init__(self, *args, **kwargs):
super(CourseForm, self).__init__(*args, **kwargs)
self.fields['min_views'].label = "Min Views:"
self.fields['max_views'].label = "Max Views:"
Courses Views.py:
class CourseListView(ListView):
model = Course
def get_queryset(self):
qs = super().get_queryset()
self.form = form = CourseForm(self.request.GET)
if form.is_valid():
min_views_query = self.request.GET.get('min_views')
max_views_query = self.request.GET.get('max_views')
if min_views_query:
qs = qs.filter(views__gte=min_views_query)
if max_views_query:
qs = qs.filter(views__lte=max_views_query)
return qs
Courses Models.py:
class Course(models.Model):
views = models.PositiveIntegerField(default=0)
@property
def total_lesson_views(self):
lessons_dictionary = Lesson.objects.filter(course=self).aggregate(Sum('views'))
return lessons_dictionary['views__sum']
class Lesson(models.Model):
course = models.ForeignKey(Course, on_delete=models.SET_NULL, null=True)
views = models.PositiveIntegerField(default=0)
如果我没理解错的话,你需要这个:
qs = Course.objects.annotate(Min("lesson__views"), Max("lesson_views")).\
aggregate(Sum("lesson__views__min"), Sum("lesson__views__max"))
该查询集应包含两个字段:lesson__views__min__sum
和 lesson__views__max__sum
,您可以使用它们进行过滤。
如果您的 Lesson
模型中已经有 views
,您可以从 Course
模型中过滤 Lessons
:
qs = Course.objects.filter(lesson__views__lt=top_limit,
lesson__views__gt=bottom__limit).\
distinct()
这会根据 个人 的观看次数选择 Lesson
,即回答 "Give me all Courses which includes at least one Lesson with its views between X and Y"。
如果您需要聚合所有 Lesson
视图然后过滤:
qs = Course.objects.annotate(Sum("lesson__views")).filter(
lesson__views__sum__lt=top_limit,
lesson__views__sum__gt=bottom_limit)
这回答了问题 "Give me all Courses which the Sum of all the views of its Lessons combined are between X and Y"。