def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) chapter = self.request.user.current_chapter qs = self.get_queryset() qs = qs.annotate(complete_link=models.Case( models.When(models.Q( chapters__chapter=chapter), models.F("chapters__pk")), default=models.Value(0), )).annotate(complete_result=models.Case( models.When(models.Q( chapters__chapter=chapter), models.Value("True")), default=models.Value(""), output_field=models.CharField(), )) # Annotate is duplicating things qs = qs.distinct() # Distinct sees incomplete/complete as different, so need to combine complete = qs.filter(complete_result=True) incomplete = qs.filter(~models.Q(pk__in=complete), complete_result="") all_tasks = complete | incomplete table = TaskTable(data=all_tasks) table.request = self.request RequestConfig(self.request, paginate={"per_page": 40}).configure(table) context["table"] = table return context
def list_view(request): actuator_list = Actuator.objects.all().annotate(pids=models.Count( models.Case( models.When(pid_controllers__active=True, then=1), models.When(pid_controllers__active=False, then=None), ))) return render(request, 'actuator/list.html', locals())
def annotate_role_status(queryset, combine=True, date=TODAY_END): qs = ( queryset.annotate( role=models.Case( models.When( models.Q(roles__start__lte=date) & models.Q(roles__end__gte=date), models.F("roles__role"), ), ) ) .annotate( role_end=models.Case( models.When( models.Q(roles__start__lte=date) & models.Q(roles__end__gte=date), models.F("roles__end"), ) ) ) .annotate( current_status=models.Case( models.When( models.Q(status__start__lte=TODAY_END) & models.Q(status__end__gte=TODAY_END), models.F("status__status"), ) ) ) ) if combine: qs = combine_annotations(qs) return qs
def target_is_complete_annotation(): """is_complete == active == reporting time-aware: the target period is over lop: the program reporting period is over event/mid-end: there is at least one data point entered """ return models.Case( models.When( models.Q( models.Q(indicator__target_frequency=Indicator.LOP) & # models.Q(indicator__program__reporting_period_end__lte=models.functions.Now()) models.Q(indicator__program__reporting_period_end__lt=utils. UTCNow())), then=models.Value(True)), models.When(models.Q( models.Q(indicator__target_frequency__in=[ Indicator.MID_END, Indicator.EVENT ]) & models.Q(results_count__gt=0)), then=models.Value(True)), models.When( models.Q( models.Q(indicator__target_frequency__in=[ f[0] for f in utils.TIME_AWARE_FREQUENCIES ]) & # models.Q(end_date__lte=models.functions.Now()) models.Q(end_date__lt=utils.UTCNow())), then=models.Value(True)), default=models.Value(False), output_field=models.BooleanField())
def __init__(self, request, preselected_task_id=None, *args, **kwargs): # https://stackoverflow.com/questions/291945/how-do-i-filter-foreignkey-choices-in-a-django-modelform super(CompleteTaskForm, self).__init__(*args, **kwargs) # populates the post available_tasks = Task.objects.filter(id__in=[ task.id for task in Task.objects.all() if task.can_be_completed_today(request.user) ]) if available_tasks.count() == 0: messages.info(request, f"Nie ma żadnych zadań, które możesz dziś wykonać") fav_tasks = [ fav_task.task.id for fav_task in FavouriteTask.objects.filter(user=request.user) ] available_tasks = available_tasks.annotate(custom_order=models.Case( models.When(id=preselected_task_id, then=models.Value(0)), models.When(id__in=fav_tasks, then=models.Value(1)), default=models.Value(2), output_field=models.IntegerField())).order_by('custom_order') self.fields['task'].queryset = available_tasks if preselected_task_id: self.initial['task'] = get_object_or_404(Task, id=preselected_task_id)
def get_context(self, request, *args, **kwargs): context = super().get_context(request, *args, **kwargs) # Get all events to display on an event index page. # Apply ascending order by start_date to upcoming events, # but for past events apply descending ordering by start_date. date_now = timezone.now().date() events = self._annotated_descendant_events() events = events.annotate(upcoming_order=models.Case( models.When(latest_date__gte=date_now, then='start_date'), default=models.Value(None), output_field=models.DateField())) events = events.annotate(past_order=models.Case( models.When(latest_date__lt=date_now, then='start_date'), default=models.Value(None), output_field=models.DateField())) events = events.order_by('upcoming_order', '-past_order') paginator = Paginator(events, settings.DEFAULT_PER_PAGE) try: events = paginator.page(request.GET.get('page')) except PageNotAnInteger: events = paginator.page(1) except EmptyPage: events = paginator.page(paginator.num_pages) context.update({ 'events': events, 'sidebar_pages': self.get_siblings().live().public(), }) context.update(get_adjacent_pages(paginator, events.number)) return context
def get_prices_converted_cases(filtered_rooms): filtered_rooms_ids = filtered_rooms.values_list('id', flat=True) original_prices = IntegralChoice.objects.filter( related_filter__name__contains='Price', room_characteristics__id__in=filtered_rooms_ids).values_list( 'room_characteristics__id', 'selected_number') price_whens = [ django_models.When(id=k, then=v) for k, v in original_prices ] original_price_cases = django_models.Case( *price_whens, default=0, output_field=django_models.IntegerField()) prices_to_convert = filtered_rooms.annotate( original_price=original_price_cases).values_list( 'id', 'original_price', 'price_currency__code') converted_prices = {} for id, original_price, from_currency in prices_to_convert: #print(id, original_price, from_currency) converted_prices[id] = int( convert_money(Money(original_price, from_currency), to_currency).amount) whens = [ django_models.When(id=k, then=v) for k, v in converted_prices.items() ] new_prices_cases = django_models.Case( *whens, default=0, output_field=django_models.IntegerField()) return new_prices_cases
def get_result(self, queryset): return queryset\ .aggregate( total_group_count=models.Count('id'), num_groups_passed=models.Count(models.Case( models.When( cached_data__last_published_feedbackset__isnull=False, cached_data__last_feedbackset=models.F('cached_data__last_published_feedbackset'), cached_data__last_published_feedbackset__grading_points__gte=models.F( 'parentnode__passing_grade_min_points'), then=1) )), num_groups_failed=models.Count(models.Case( models.When( cached_data__last_published_feedbackset__isnull=False, cached_data__last_feedbackset=models.F('cached_data__last_published_feedbackset'), cached_data__last_published_feedbackset__grading_points__lt=models.F( 'parentnode__passing_grade_min_points'), then=1) )), num_groups_not_corrected=models.Count(models.Case( models.When( models.Q(cached_data__last_feedbackset__grading_published_datetime__isnull=True), then=1) )))
def with_relevance(self): """ Annotates "relevance" value based on next date and/or status. Use with with_next_date() ! Relevance: 1) if private/canceled: -1 2) if event coming up OR same day as today: +1 3) if event passed: 0 Returns: QuerySet """ now = timezone.now() return self.annotate(relevance=models.Case( models.When( models.Q(published__isnull=True) | models.Q(canceled__isnull=False), then=models.Value(-1), ), models.When( models.Q( models.Q(next_date__gte=now) | models.Q( next_date__day=now.day, next_date__month=now.month, next_date__year=now.year, )), then=models.Value(1), ), default=0, output_field=models.IntegerField(), ))
def get_queryset(self): return super().get_queryset() \ .annotate(ticket_count=models.Sum( models.Case( models.When( orderitem__order__refunded=True, then=0 ), models.When( orderitem__order__billed_total='', then=0 ), models.When( orderitem__order__billed_total__isnull=True, then=0 ), default=1, output_field=models.IntegerField(), ))) \ .annotate(sold_out=models.Case( models.When( ticket_count__lt=F('capacity'), then=models.Value(False), ), default=True, output_field=models.BooleanField(), ))
def get_queryset(self): self.queryset = super(CommentsList, self).get_queryset().filter( models.Q(post_id=self.post_id) & (models.Q(is_deleted=False) | models.Q(post__author_id=self.request.user.id)) ).annotate( # likes_count=models.Sum( # models.Case( # models.When(likes__liked=True, then=1), # default=0, output_field=models.IntegerField() # ) # ), is_liked=models.Sum(models.Case( models.When(likes__liked=True, likes__user_id=self.request.user.id, then=1), default=0, output_field=models.IntegerField()), output_field=models.BooleanField()), is_invisible=models.Case( models.When(models.Q(is_deleted=True) & models.Q(post__author_id=self.request.user.id), then=True), default=False, output_field=models.BooleanField())) return self.queryset
def lease_doc_number_by_province(self, request, country: str = None): """ lessor -- Filter by lessor name (query param) """ lessor = request.query_params.get('lessor', None) q = LeaseDocument.objects \ .values('address_country', 'address_state_province') \ .annotate( leases_number_country=models.Count( 'address_country') if not lessor else models.Count( models.Case(models.When(lessor=lessor, then=1)))) \ .annotate( leases_number=models.Count( 'address_state_province') if not lessor else models.Count( models.Case(models.When(lessor=lessor, then=1)))) \ .order_by('-leases_number', 'address_state_province') if country != 'all': q = q.filter(address_country=country) rows = list(q) data = {'rows': [{'address_country': row['address_country'], 'address_country_code': LeaseMapViewSet._country_short( row['address_country']), 'address_state_province': row['address_state_province'], 'leases_number': row['leases_number']} for row in rows if row['address_country']]} return JsonResponse(data)
def delete(self, *args, **kwargs): start_date = self.start_date transaction_type = self.transaction_type sorted_price_periods = BasePrice.objects.filter( transaction_type=transaction_type ).annotate( relevance=models.Case( models.When(start_date__gt=start_date, then=1), models.When(start_date__lt=start_date, then=2), output_field=models.IntegerField(), ) ).order_by('relevance', 'start_date') previous_price_period = sorted_price_periods.filter(relevance=2).last() next_price_period = sorted_price_periods.filter(relevance=1).first() if next_price_period: end_date = next_price_period.start_date - datetime.timedelta(days=1) else: end_date = datetime.date.today() if previous_price_period: Transaction.objects.filter( transaction_type=transaction_type, date__gte=previous_price_period.start_date, date__lte=end_date, ).update(base_ip_related_price_per_reaction=previous_price_period.price_per_reaction) else: Transaction.objects.filter( transaction_type=transaction_type, date__lte=end_date, ).update(base_ip_related_price_per_reaction=0) super().delete(*args, **kwargs)
def review_order(self): review_order = [ STAFF_GROUP_NAME, COMMUNITY_REVIEWER_GROUP_NAME, REVIEWER_GROUP_NAME, ] ordering = [ models.When(type__name=review_type, then=models.Value(i)) for i, review_type in enumerate(review_order) ] return self.exclude( # Remove people from the list who are opinionated but # didn't review, they appear elsewhere opinions__isnull=False, review__isnull=True, ).annotate( type_order=models.Case( *ordering, output_field=models.IntegerField(), ), has_review=models.Case( models.When(review__isnull=True, then=models.Value(1)), models.When(review__is_draft=True, then=models.Value(1)), default=models.Value(0), output_field=models.IntegerField(), ) ).order_by( 'type_order', 'has_review', F('role__order').asc(nulls_last=True), ).select_related( 'reviewer', 'role', )
def viral_video_detail(request, pk): yesterday = datetime.date.today() - datetime.timedelta(days=1) qs = ViralVideo.objects.annotate( total_views=models.F("authenticated_views") + models.F("anonymous_views"), label=models.Case(models.When(total_views__gt=POPULAR_FROM, then=models.Value("popular")), models.When(created__gt=yesterday, then=models.Value("new")), default=models.Value("cool"), output_field=models.CharField())) # DEBUG: check the SQL query that Django ORM generates logger.debug(f"Query: {qs.query}") qs = qs.filter(pk=pk) if request.user.is_authenticated: qs.update(authenticated_views=models.F("authenticated_views") + 1) else: qs.update(anonymous_views=models.F("anonymous_views") + 1) video = get_object_or_404(qs) return render(request, "viral_videos/viral_video_detail.html", {'video': video})
def mid_end_value_annotation(count): values_subquery = Result.objects.select_related(None).prefetch_related( None).filter( periodic_target__isnull=False, indicator=models.OuterRef('pk'), periodic_target__customsort__lte=count).order_by('-date_collected') return models.Case( models.When(unit_of_measure_type=Indicator.PERCENTAGE, then=models.Subquery( values_subquery.filter( periodic_target__customsort=count).values( 'achieved')[:1])), models.When( is_cumulative=True, then=models.Subquery( values_subquery.order_by().values('indicator').annotate( this_period_count=models.Sum( models.Case(models.When( periodic_target__customsort=count, then=1), output_field=models.IntegerField()))). annotate(achieved_sum=models.Case( models.When(this_period_count__gt=0, then=models.Sum('achieved')), default=models.Value(None))).values('achieved_sum')[:1])), default=models.Subquery(values_subquery.order_by().filter( periodic_target__customsort=count).values('indicator').annotate( achieved_sum=models.Sum('achieved')).values('achieved_sum') [:1]), output_field=models.DecimalField(decimal_places=2))
def current_races(self): return self.object.race_set.exclude(state__in=[ models.RaceStates.finished, models.RaceStates.cancelled, ]).annotate( state_sort=db_models.Case( # Open/Invitational db_models.When( state__in=[ models.RaceStates.open, models.RaceStates.invitational ], then=1, ), # Pending/In progress db_models.When( state=models.RaceStates.pending, then=2, ), db_models.When( state=models.RaceStates.in_progress, then=2, ), output_field=db_models.PositiveSmallIntegerField(), default=0, ), ).order_by('state_sort', 'opened_at').all()
def indicator_over_under_annotation(): """annotates indicators with how close to on-track they are: -1 : under target by a 15% margin 0 : within 15% of target 1 : over target by a 15% margin None: nonreporting indicator""" over_scope = 1 + Indicator.ONSCOPE_MARGIN under_scope = 1 - Indicator.ONSCOPE_MARGIN return models.Case( # None for indicators missing targets or data: models.When(models.Q(reporting=False) | models.Q(lop_percent_met_progress__isnull=True), then=models.Value(None)), models.When( # over is negative if DOC is Negative models.Q(lop_percent_met_progress__gt=over_scope) & models.Q( direction_of_change=Indicator.DIRECTION_OF_CHANGE_NEGATIVE), then=models.Value(-1)), models.When(lop_percent_met_progress__gt=over_scope, then=models.Value(1)), models.When( # under is positive if DOC is Negative: models.Q(lop_percent_met_progress__lt=under_scope) & models.Q( direction_of_change=Indicator.DIRECTION_OF_CHANGE_NEGATIVE), then=models.Value(1)), models.When(lop_percent_met_progress__lt=under_scope, then=models.Value(-1)), default=models.Value(0), output_field=models.IntegerField(null=True))
def indicator_lop_target_calculated_annotation(): """annotates an indicator with the sum of targets for the entire program (not taking active/inactive targets) into account - NOT for progress, for results display only""" return models.Case( models.When(models.Q( models.Q( models.Q(unit_of_measure_type=Indicator.PERCENTAGE) | models.Q(is_cumulative=True)) & models.Q( target_frequency__in=[Indicator.MID_END, Indicator.EVENT])), then=models.Subquery(PeriodicTarget.objects.filter( indicator=models.OuterRef('pk')).order_by( '-customsort').values('target')[:1], output_field=models.FloatField())), models.When(models.Q( models.Q(unit_of_measure_type=Indicator.PERCENTAGE) | models.Q(is_cumulative=True)), then=models.Subquery(PeriodicTarget.objects.filter( indicator=models.OuterRef('pk')).order_by( '-end_date').values('target')[:1], output_field=models.FloatField())), default=models.Subquery( PeriodicTarget.objects.filter(indicator=models.OuterRef( 'pk')).order_by().values('indicator').annotate( target_sum=models.Sum('target')).values('target_sum')[:1], output_field=models.FloatField()))
def get_queryset(self, *args, **kwargs): qs = super(DynaformReportListView, self).get_queryset(*args, **kwargs) date_from = datetime.date.today() - datetime.timedelta(30) date_to = datetime.date.today() options = self.request.GET if options.get('date_from'): date_from = datetime.datetime.strptime(options['date_from'], '%Y-%m-%d').date() if options.get('date_to'): date_to = datetime.datetime.strptime(options['date_to'], '%Y-%m-%d').date() date_from_ant = date_from - datetime.timedelta(30) date_to_ant = date_to - datetime.timedelta(30) return qs.values('sender', 'object_form', 'object_form_id').annotate( conversiones=models.Count( models.Case( models.When(pub_date__range=[date_from, date_to], then='object_form'))), conversiones_anterior=models.Count( models.Case( models.When(pub_date__range=[date_from_ant, date_to_ant], then='object_form'))))
def delete_comment(request, obj, user): comment = obj if comment.post.author.id == user.id: comment.change_is_deleted() context = { 'comment': Comment.objects.filter(id=comment.id).filter( models.Q(post_id=comment.post.id) & (models.Q(is_deleted=False) | models.Q(post__author_id=user.id))). annotate( # likes_count=models.Sum( # models.Case( # models.When(likes__liked=True, then=1), # default=0, output_field=models.IntegerField() # ) # ), is_liked=models.Sum(models.Case( models.When(likes__liked=True, likes__user_id=user.id, then=1), default=0, output_field=models.IntegerField()), output_field=models.BooleanField()), is_invisible=models.Case( models.When(models.Q(is_deleted=True) & models.Q(post__author_id=user.id), then=True), default=False, output_field=models.BooleanField())).first() } return render(request, 'comments/comment.html', context) return HttpResponse(content="Can't delete", status=404)
def get_desempenho(self, *args): """ Retorna o resulta de erros e acertos de acordo com o agrupamento de atributos passado pelo parâmetro *arg. Esse método é semelhante ao desempenho, desempenho_aula dessa classe e outros com a diferênça de que os parâmentros de agrupamento pode ser passados livrimente em uma lista. Ex. de uso: filters = {'aluno__escola__id':1, 'exercicio__aula__serie':5, 'aluno__serie_atual':5} fields = [aluno__escola', 'exercicio__aula__disciplina'] Resposta.objects.filter(**filters).calc_desempenho(*fields) TODO: Refatorar todos os métodos de desempenho para utilizarem get_desempenho como base. :param args: :return: """ values = self.values(*args).annotate( corretas=models.Sum( models.Case(models.When(alternativa__correta=True, then=1), default=0, output_field=models.IntegerField())), erradas=models.Sum( models.Case(models.When(alternativa__correta=False, then=1), default=0, output_field=models.IntegerField())), total=models.F('corretas') + models.F('erradas'), aproveitamento=models.F('corretas') * 100 / (models.F('corretas') + models.F('erradas'))).order_by( 'exercicio__aula__id', 'exercicio__aula__ordem') return values
def opponents(self, player: Player) -> typing.Iterable[str]: return self.duels(player).values_list( models.Case( models.When(player_1=player, then='player_2'), models.When(player_2=player, then='player_1') ), flat=True )
def target_actual_annotation(): """ value for "actual" on this target's row in the Results Table: - NUMBER/cumulative: sum of results in this periodic target period, - NUMBER/noncumulative: sum of results from all periods up to and including this one - PERCENTAGE: latest result in this period """ return models.Case( models.When( models.Q( models.Q(indicator__unit_of_measure_type=Indicator.PERCENTAGE) & models.Q(indicator__target_frequency__in=[ f[0] for f in utils.TIME_AWARE_FREQUENCIES ])), then=models.Subquery( Result.objects.filter(periodic_target=models.OuterRef('pk')). order_by('-date_collected').values('achieved')[:1], )), models.When(models.Q( models.Q(indicator__unit_of_measure_type=Indicator.PERCENTAGE) & ~models.Q(indicator__target_frequency__in=[ f[0] for f in utils.TIME_AWARE_FREQUENCIES ])), then=models.Subquery( Result.objects.filter( periodic_target=models.OuterRef('pk')).order_by( '-date_collected').values('achieved')[:1], )), models.When( models.Q( models.Q(indicator__unit_of_measure_type=Indicator.NUMBER) & models.Q(indicator__is_cumulative=True) & models.Q(indicator__target_frequency__in=[ f[0] for f in utils.TIME_AWARE_FREQUENCIES ]) & models.Q(results_count__gt=0)), then=models.Subquery( Result.objects.filter( models.Q(indicator=models.OuterRef('indicator')) & models.Q(periodic_target__end_date__lte=models.OuterRef( 'end_date'))).order_by().values('indicator').annotate( achieved_sum=models.Sum('achieved')).values( 'achieved_sum')[:1])), models.When(models.Q( models.Q(indicator__unit_of_measure_type=Indicator.NUMBER) & models.Q(indicator__is_cumulative=True) & ~models.Q(indicator__target_frequency__in=[ f[0] for f in utils.TIME_AWARE_FREQUENCIES ]) & models.Q(results_count__gt=0)), then=models.Subquery( Result.objects.filter( models.Q(indicator=models.OuterRef('indicator')) & models.Q(periodic_target__customsort__lte=models. OuterRef('customsort'))).order_by(). values('indicator').annotate(achieved_sum=models.Sum( 'achieved')).values('achieved_sum')[:1])), default=models.Subquery( Result.objects.filter(periodic_target=models.OuterRef( 'pk')).order_by().values('periodic_target').annotate( achieved_sum=models.Sum('achieved')).values('achieved_sum') [:1]), output_field=models.DecimalField(decimal_places=2))
def likes(self, model, object_id): qs = self.values('content_type').filter( content_type__app_label='poll', content_type__model=model, object_id=object_id).annotate( like=models.Count(models.Case(models.When(like=True, then=1))), dislike=models.Count(models.Case(models.When(like=False, then=1))), total=models.Count('like') ) if qs: return qs[0]
def indicator_lop_actual_progress_annotation(): """actual progress: - only data associated with active periodic targets - summed if NUMBER, latest if PERCENTAGE """ return models.Case( models.When( models.Q( models.Q( models.Q( models.Q(target_frequency=Indicator.LOP) & # models.Q(program__reporting_period_end__lte=models.functions.Now()) models.Q(program__reporting_period_end__lt=UTCNow())) | models.Q(target_frequency__in=[ Indicator.MID_END, Indicator.EVENT ])) & models.Q(unit_of_measure_type=Indicator.PERCENTAGE)), then=models.Subquery( Result.objects.filter( periodic_target__isnull=False, indicator=models.OuterRef('pk')).order_by( '-date_collected').values('achieved')[:1])), models.When( models.Q( models.Q( models.Q(target_frequency=Indicator.LOP) & # models.Q(program__reporting_period_end__lte=models.functions.Now()) models.Q(program__reporting_period_end__lt=UTCNow())) | models. Q(target_frequency__in=[Indicator.MID_END, Indicator.EVENT])), then=models.Subquery( Result.objects.filter( periodic_target__isnull=False, indicator=models.OuterRef('pk')).order_by().values( 'indicator').annotate(actual_sum=models.Sum( 'achieved')).values('actual_sum')[:1])), models.When(models.Q( models.Q( target_frequency__in=[f[0] for f in TIME_AWARE_FREQUENCIES]) & models.Q(unit_of_measure_type=Indicator.PERCENTAGE)), then=models.Subquery( Result.objects.filter( models.Q(periodic_target__isnull=False) & models.Q(indicator=models.OuterRef('pk')) & models.Q(periodic_target__end_date__lt=UTCNow()) ).order_by('-date_collected').values('achieved')[:1])), models.When( target_frequency__in=[f[0] for f in TIME_AWARE_FREQUENCIES], then=models.Subquery( Result.objects.filter( models.Q(periodic_target__isnull=False) & models.Q(indicator=models.OuterRef('pk')) & # models.Q(periodic_target__end_date__lt=models.functions.Now()) models.Q(periodic_target__end_date__lt=UTCNow())).order_by( ).values('indicator').annotate(actual_sum=models.Sum( 'achieved')).values('actual_sum')[:1])), default=models.Value(None), output_field=models.DecimalField(decimal_places=2))
def with_class(self): return self.all().annotate( _class=models.Case( models.When(rating__gte=4, then=models.Value('positive')), models.When(rating__lt=4, rating__gte=3, then=models.Value('neutral')), models.When(rating__lt=3, then=models.Value('negative')), output_field=models.CharField(), ) )
def get_queryset(self): return super(StageAttendanceDefaultManager, self).get_queryset().annotate(type_order=models.Case( models.When(role__type="rep", then=0), models.When(role__type="opp", then=1), models.When(role__type="rev", then=2), models.When(role__type="obs", then=3), output_field=models.IntegerField(), )).order_by('type_order')
def get_queryset(self): qs = super().get_queryset() qs = qs.annotate(alumni=models.Case( models.When(user__member__isnull=True, then=False), models.When(user__member__isnull=False, then=True), default=False, output_field=models.BooleanField(), )) return qs
def query_all_issues_sorted(): return Issue.objects.annotate(custom_order=models.Case( models.When(issue='Winter', then=models.Value(0)), models.When(issue='Spring', then=models.Value(1)), models.When(issue='Commencement', then=models.Value(2)), models.When(issue='Summer', then=models.Value(3)), models.When(issue='Fall', then=models.Value(4)), default=models.Value(5), output_field=models.IntegerField(), )).order_by('-year', '-custom_order')