import django_filters from .models import ( Article, Magazine, MagazineCategory, Organize, OrganizeCategory, Professor, Subject, WorkGroup, WorkGroupTerm, ) class NumberInFilter(django_filters.BaseInFilter, django_filters.NumberFilter): """支持 ?year=2023,2024 或多值 in 查询。""" class ArticleFilter(django_filters.FilterSet): type = NumberInFilter(field_name="type") year = NumberInFilter(field_name="year") year_gte = django_filters.NumberFilter(field_name="year", lookup_expr="gte") year_lte = django_filters.NumberFilter(field_name="year", lookup_expr="lte") organize = NumberInFilter(field_name="organizes") magazine = NumberInFilter(field_name="magazines") subject = NumberInFilter(field_name="subjects") search = django_filters.CharFilter(field_name="title", lookup_expr="icontains") ordering = django_filters.OrderingFilter( fields=( ("score", "score"), ("year", "year"), ("rank", "rank"), ("push_date", "push_date"), ("created_at", "created_at"), ) ) class Meta: model = Article fields = ["type", "year", "is_disabled"] class OrganizeFilter(django_filters.FilterSet): search = django_filters.CharFilter(field_name="name", lookup_expr="icontains") category = django_filters.NumberFilter(field_name="category_id") class Meta: model = Organize fields = ["category", "is_disabled"] class MagazineFilter(django_filters.FilterSet): search = django_filters.CharFilter(field_name="name", lookup_expr="icontains") subject = django_filters.NumberFilter(field_name="subjects") category = django_filters.NumberFilter(field_name="category_id") class Meta: model = Magazine fields = ["category", "is_disabled"] class ProfessorFilter(django_filters.FilterSet): search = django_filters.CharFilter(field_name="name", lookup_expr="icontains") term = django_filters.NumberFilter(method="filter_term_tree") workgroup = django_filters.NumberFilter(field_name="terms__workgroup") class Meta: model = Professor fields = ["type", "is_disabled"] def filter_term_tree(self, queryset, name, value): """包含该届及其同届下级分委会。""" ids = {int(value)} frontier = [int(value)] while frontier: children = list( WorkGroupTerm.objects.filter(parent_id__in=frontier).values_list( "id", flat=True ) ) frontier = [cid for cid in children if cid not in ids] ids.update(frontier) return queryset.filter(terms__in=ids).distinct() class WorkGroupFilter(django_filters.FilterSet): class Meta: model = WorkGroup fields = ["parent", "is_disabled"] class WorkGroupTermFilter(django_filters.FilterSet): class Meta: model = WorkGroupTerm fields = ["workgroup", "parent", "is_current", "is_disabled"] class SubjectFilter(django_filters.FilterSet): class Meta: model = Subject fields = ["parent", "is_disabled"] class OrganizeCategoryFilter(django_filters.FilterSet): class Meta: model = OrganizeCategory fields = ["parent", "is_disabled"] class MagazineCategoryFilter(django_filters.FilterSet): class Meta: model = MagazineCategory fields = ["parent", "is_disabled"]