Changeset d7557b8


Ignore:
Timestamp:
Feb 9, 2013, 1:53:21 AM (14 years ago)
Author:
Alex Dehnert <adehnert@…>
Branches:
master, stable, stage
Children:
62f73df
Parents:
ea8e8b6
git-author:
Alex Dehnert <adehnert@…> (02/09/13 01:53:21)
git-committer:
Alex Dehnert <adehnert@…> (02/09/13 01:53:21)
Message:

Proof-of-concept reporting filters (ASA-#193)

Add proof-of-concept support for extensible filtering of the reporting page,
beyond just the fields on the Group object. At the moment, this is just a few
space-related filters, but in the future this might include groups missing
membership confirmations, groups whose presidents aren't students, groups who
have filled out the FYSM, etc..

Location:
asadb
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • asadb/groups/models.py

    rafc5348 rd7557b8  
     1# -*- coding: utf8 -*-
     2
    13from django.conf import settings
    24from django.db import models
     5from django.core.exceptions import ValidationError
    36from django.core.validators import RegexValidator
    47from django.contrib.auth.models import User
     
    570573    class Meta:
    571574        verbose_name = "Athena (Moira) account"
     575
     576
     577
     578class GroupFilter(object):
     579    def __init__(self, **kwargs):
     580        self.qs_thunk = kwargs['qs_thunk']
     581        self.name = kwargs['name']
     582        self.description = kwargs['desc']
     583
     584    def queryset(self, ):
     585        return self.qs_thunk()
     586
     587
     588class GroupFilterRegistry(object):
     589    def __init__(self, ):
     590        self.filters = {}
     591        self.filter_groups = {}
     592
     593    def register_group(self, name, slug, ):
     594        if slug in self.filter_groups:
     595            raise ValueError, "Duplicate filter group %s" % (slug, )
     596        if slug in self.filters:
     597            raise ValueError, "Group %s matches filter" % (slug, )
     598        self.filter_groups[slug] = dict(
     599            name=name,
     600            filters=[],
     601        )
     602        self.filters[slug] = GroupFilter(
     603            qs_thunk=None,
     604            name=name,
     605            desc=None,
     606        )
     607
     608    def register(self, **kwargs):
     609        slug = kwargs.pop('slug')
     610        group = kwargs.pop('group')
     611        if group not in self.filter_groups:
     612            raise KeyError, "Unknown filter group %s" % (group, )
     613        fltr = GroupFilter(**kwargs)
     614        if slug in self.filters:
     615            raise ValueError, "Duplicate filter %s" % (slug, )
     616        self.filters[slug] = fltr
     617        self.filter_groups[group]['filters'].append(slug)
     618
     619    def get(self, slug):
     620        return self.filters[slug]
     621
     622    def get_choices(self, ):
     623        choices = []
     624        for group_slug, grp in self.filter_groups.items():
     625            choices.append((group_slug, "[%s]" % (grp['name'], )))
     626            for filter_slug in grp['filters']:
     627                choices.append((filter_slug, self.filters[filter_slug].name))
     628            choices.append(("", ""))
     629        return choices[:-1]
     630
     631    def validate_filter_slug(self, value, ):
     632        for slug in value:
     633            if slug == "":
     634                raise ValidationError("Please select only filters")
     635            if slug not in self.filters:
     636                raise ValidationError("%s is an unknown filter" % (slug, ))
     637            if slug in self.filter_groups:
     638                raise ValidationError(u"%s is a filter group — please select only filters" % (self.filter_groups[slug]['name'], ))
     639
     640
     641filter_registry = GroupFilterRegistry()
     642filter_registry.register_group(name="People", slug='people', )
     643filter_registry.register_group(name="Space", slug='space', )
     644filter_registry.register_group(name="FYSM", slug='fysm', )
  • asadb/groups/views.py

    r8d3b651 rd7557b8  
    10791079
    10801080class ReportingForm(form_utils.forms.BetterForm):
     1081    special_filters = forms.fields.MultipleChoiceField(
     1082        choices=[],
     1083        widget=forms.SelectMultiple(attrs={'size': 10}),
     1084        validators=[groups.models.filter_registry.validate_filter_slug],
     1085        required=False,
     1086    )
     1087
    10811088    basic_fields_choices = groups.models.Group.reporting_fields()
    10821089    basic_fields_labels = dict(basic_fields_choices) # name -> verbose_name
     
    11171124            ('filter', {
    11181125                'legend': 'Filter Groups',
    1119                 'fields': ['name', 'abbreviation', 'activity_category', 'group_class', 'group_status', 'group_funding', ],
     1126                'fields': [
     1127                    'name', 'abbreviation',
     1128                    'activity_category', 'group_class', 'group_status', 'group_funding',
     1129                    'special_filters',
     1130                ],
    11201131            }),
    11211132            ('fields', {
     
    11281139            }),
    11291140        ]
     1141
     1142    def __init__(self, *args, **kwargs):
     1143        super(ReportingForm, self).__init__(*args, **kwargs)
     1144
     1145        registry = groups.models.filter_registry
     1146        self.fields['special_filters'].choices = registry.get_choices()
    11301147
    11311148class GroupReportingFilter(GroupFilter):
     
    11901207        # Set up query
    11911208        qs = groups_filterset.qs
     1209        for fltr_slug in form.cleaned_data['special_filters']:
     1210            fltr = groups.models.filter_registry.get(fltr_slug)
     1211            qs = qs.filter(pk__in=fltr.queryset())
     1212
    11921213        # Prefetch foreign keys
    11931214        prefetch_fields = groups.models.Group.reporting_prefetch()
  • asadb/space/models.py

    r7eea15c rd7557b8  
    126126
    127127
     128groups.models.filter_registry.register(
     129    group='space',
     130    slug='space:owners',
     131    name='Space owners',
     132    desc='Groups with space',
     133    qs_thunk=lambda: SpaceAssignment.current.values('group'),
     134)
     135
     136def building_filter(building):
     137    building_assignments = SpaceAssignment.current.filter(
     138        space__number__startswith="%s-" % (building, ),
     139    )
     140    owners = groups.models.Group.objects.filter(
     141        pk__in=building_assignments.values('group'),
     142    )
     143    return owners
     144
     145groups.models.filter_registry.register(
     146    group='space',
     147    slug='space:w20',
     148    name='W20 owners',
     149    desc='Owners of W20 space',
     150    qs_thunk=lambda: building_filter('W20'),
     151)
     152groups.models.filter_registry.register(
     153    group='space',
     154    slug='space:walker',
     155    name='Walker owners',
     156    desc='Owners of Walker space',
     157    qs_thunk=lambda: building_filter('50'),
     158)
     159
    128160class CurrentACLEntryManager(models.Manager):
    129161    def get_query_set(self, ):
Note: See TracChangeset for help on using the changeset viewer.