Skip to content
This repository has been archived by the owner on Jun 18, 2020. It is now read-only.

Commit

Permalink
FilteredCrudRestController to the max!
Browse files Browse the repository at this point in the history
  • Loading branch information
moschlar committed Apr 16, 2012
1 parent 9484e7f commit a1f9151
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 18 deletions.
3 changes: 3 additions & 0 deletions SAUCE.egg-info/SOURCES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ sauce/config/middleware.py
sauce/controllers/__init__.py
sauce/controllers/admin.py
sauce/controllers/assignments.py
sauce/controllers/crc.py
sauce/controllers/error.py
sauce/controllers/event_admin.py
sauce/controllers/events.py
sauce/controllers/lessons.py
sauce/controllers/news.py
Expand All @@ -27,6 +29,7 @@ sauce/controllers/scores.py
sauce/controllers/sheets.py
sauce/controllers/submissions.py
sauce/controllers/template.py
sauce/controllers/tests.py
sauce/controllers/user.py
sauce/i18n/ru/LC_MESSAGES/sauce.po
sauce/lib/__init__.py
Expand Down
161 changes: 149 additions & 12 deletions sauce/controllers/crc.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
@author: moschlar
'''
#TODO: Unified field_order regarding common elements

import logging

Expand All @@ -13,20 +14,28 @@
from sprox.tablebase import TableBase
from sprox.fillerbase import TableFiller, FillerBase, EditFormFiller

from sauce.model import DBSession, Event, Lesson, Team, Student
from sauce.model import DBSession, Event, Lesson, Team, Student, Sheet, Assignment, Test
from sprox.formbase import AddRecordForm, EditableForm

from tw.forms import TextField
from tw.forms import TextField, BooleanRadioButtonList, SingleSelectField, FileField
from tw.forms.validators import Email, FieldsMatch, Schema
from tw.tinymce import TinyMCE

log = logging.getLogger(__name__)

#--------------------------------------------------------------------------------

passwordValidator = Schema(chained_validators=(FieldsMatch('password',
'_password',
messages={'invalidNoMatch':
"Passwords do not match"}),))

#--------------------------------------------------------------------------------

class FilteredCrudRestController(EasyCrudRestController):
'''Generic base class for CrudRestControllers with filters'''

# Merely a reminder of possible options
__table_options__ = {
'__omit_fields__':[],
'__field_order__':[],
Expand All @@ -35,26 +44,32 @@ class FilteredCrudRestController(EasyCrudRestController):
'__hide_fields__':[],
'__field_order__':[],
'__field_widget_types__':{},
'__field_widget_args__':{},
}

def __init__(self, model=None, filters=[], filter_bys={},
table_options={}, form_options={}, menu_items={}):
'''Initialize FilteredCrudRestController with given options
Although not required, model should be given.
table_options and form_options are merged into the defaults
'''

if model:
self.model = model

super(FilteredCrudRestController, self).__init__(DBSession)

# Custom getter function respecting provided filters
def custom_do_get_provider_count_and_objs(**kw):
'''Custom getter function respecting provided filters and filter_bys'''
qry = model.query
if filters:
qry = qry.filter(*filters)
if filter_bys:
qry = qry.filter_by(**filter_bys)
objs = qry.all()
return len(objs), objs

# Assign custom getter function to table_filler
self.table_filler._do_get_provider_count_and_objs = custom_do_get_provider_count_and_objs

# Update table options
Expand All @@ -76,11 +91,6 @@ def custom_do_get_provider_count_and_objs(**kw):

#--------------------------------------------------------------------------------

passwordValidator = Schema(chained_validators=(FieldsMatch('password',
'_password',
messages={'invalidNoMatch':
"Passwords do not match"}),))

class TeamsCrudController(FilteredCrudRestController):

model = Team
Expand All @@ -90,6 +100,8 @@ class TeamsCrudController(FilteredCrudRestController):
'__field_order__':['id', 'name', 'lesson', 'students'],
}
__form_options__ = {
'__omit_fields__':[],
'__field_order__':['id', 'name', 'lesson', 'students'],
'__field_widget_types__':{'name':TextField},
}

Expand All @@ -102,7 +114,7 @@ class StudentsCrudController(FilteredCrudRestController):
'__field_order__':['id', 'user_name', 'display_name', 'email_address', 'teams', 'created'],
}
__form_options__ = {
'__omit_fields__':['id', 'submissions', 'type', 'created'],
'__omit_fields__':['submissions', 'type', 'created'],
'__field_order__':['id', 'user_name', 'display_name', 'email_address', 'teams', 'password', '_password', 'groups'],
'__field_widget_types__':{'user_name':TextField, 'display_name':TextField, 'email_address':TextField},
'__base_validator__':passwordValidator,
Expand All @@ -118,10 +130,135 @@ class LessonsCrudController(FilteredCrudRestController):
}
__form_options__ = {
# '__hide_fields__':['event', 'teacher'], # If we hide them, creation of new lessons is not possible
'__field_order__':['lesson_id', 'name', 'teacher', 'teams'],
'__field_order__':['id', 'lesson_id', 'name', 'teacher', 'teams'],
'__field_widget_types__':{'name':TextField},
}

#--------------------------------------------------------------------------------
class SheetsCrudController(FilteredCrudRestController):

model = Sheet

__table_options__ = {
'__omit_fields__':['id', 'description', 'event_id', 'event', 'teacher_id', '_url'],
'__field_order__':['sheet_id', 'name', '_start_time', '_end_time',
'public', 'teacher'],
}
__form_options__ = {
'__hide_fields__':['_url'],
'__field_order__':['id', 'sheet_id', 'name', 'description',
'_start_time', '_end_time', 'public', 'teacher'],
'__field_widget_types__':{'name':TextField, 'description':TinyMCE, 'public':BooleanRadioButtonList},
'__field_widget_args__':{'_start_time':{'default': u'', 'help_text': u'Leave empty to use value from event'},
'_end_time':{'default': u'', 'help_text': u'Leave empty to use value from event'},}
}

class AssignmentsCrudController(FilteredCrudRestController):

model = Assignment

__table_options__ = {
'__omit_fields__':['id', 'event_id', '_event', 'teacher_id', 'teacher', '_teacher',
'sheet_id', 'description', 'tests', 'submissions', 'show_compiler_msg'],
'__field_order__':['assignment_id', 'name', 'sheet',
'_start_time', '_end_time', 'timeout',
'allowed_languages', 'public'],
}
__form_options__ = {
'__hide_fields__':['tests', 'submissions', '_event'],
'__field_order__':['id', 'assignment_id', 'sheet', 'name', 'description',
'_start_time', '_end_time', 'timeout', 'allowed_languages',
'show_compiler_msg', 'tests', 'public', 'teacher'],
'__field_widget_types__':{'name':TextField, 'description':TinyMCE,
'show_compiler_msg':BooleanRadioButtonList,
'public': BooleanRadioButtonList},
'__field_widget_args__':{'_start_time':{'default': u'', 'help_text': u'Leave empty to use value from event'},
'_end_time':{'default': u'', 'help_text': u'Leave empty to use value from event'},}
}

class TestsCrudController(FilteredCrudRestController):
#TODO: FileUpload validation

model = Test

__table_options__ = {
'__omit_fields__':['id', 'assignment_id', 'input_data', 'output_data',
'separator', 'ignore_case', 'splitlines', 'split',
'parse_int', 'parse_float', 'sort',
'teacher_id', 'teacher', 'testruns'],
'__field_order__':['assignment', 'visible', 'argv']
}
__form_options__ = {
'__hide_fields__':['testruns'],
'__field_order__':['id', 'assignment', 'visible', '_timeout', 'argv',
'input_type', 'output_type', 'input_filename', 'output_filename',
'input_data', 'output_data', 'separator',
'ignore_case', 'splitlines', 'split',
'parse_int', 'parse_float', 'sort'],
'__field_widget_types__':{'argv':TextField,
'input_filename':TextField, 'output_filename':TextField,
'input_type': SingleSelectField,
'output_type': SingleSelectField,
'input_data': FileField, 'output_data': FileField,
#'separator':BooleanRadioButtonList,
'ignore_case':BooleanRadioButtonList,
'splitlines':BooleanRadioButtonList,
'split':BooleanRadioButtonList,
'parse_int':BooleanRadioButtonList,
'parse_float':BooleanRadioButtonList,
'sort':BooleanRadioButtonList,
},
'__field_widget_args__':{'input_type': dict(options=[('stdin','stdin'), ('file','file')]),
'output_type': dict(options=[('stdout','stdout'), ('file','file')]),
}
}

class EventsCrudController(FilteredCrudRestController):
#TODO: Wrong field_order in form

model = Event

__table_options__ = {
'__omit_fields__':['id', 'description', 'teacher_id', 'password',
'assignments', 'lessons', 'sheets', 'news',
],
'__field_order__':['type', '_url', 'name', 'teacher', 'public',
'start_time', 'end_time', 'teachers'],
}
__form_options__ = {
'__hide_fields__':['assignments', 'sheets', 'news'],
'__field_order__':['type', '_url', 'name', 'description' 'teacher', 'public',
'password', 'start_time', 'end_time', 'teachers'],
'__field_widget_types__':{'name':TextField, 'description':TinyMCE,
'public': BooleanRadioButtonList, '_url':TextField,
'type': SingleSelectField, 'password':TextField,
},
'__field_widget_args__':{
'type': dict(options=[('course','Course'), ('contest','Contest')]),
}
}


























30 changes: 24 additions & 6 deletions sauce/controllers/event_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
#from repoze.what import predicates

# project specific imports
from sauce.model import Lesson, Team, Student
from sauce.controllers.crc import FilteredCrudRestController, TeamsCrudController, StudentsCrudController, LessonsCrudController
from sauce.model import Lesson, Team, Student, Sheet, Assignment, Test, Event
from sauce.controllers.crc import FilteredCrudRestController, TeamsCrudController, StudentsCrudController, LessonsCrudController, SheetsCrudController, AssignmentsCrudController,\
TestsCrudController, EventsCrudController
from sauce.lib.base import BaseController

log = logging.getLogger(__name__)
Expand All @@ -28,14 +29,31 @@ def __init__(self, event, **kw):

self.event = event

menu_items = {'lesson': Lesson}
model_items = [Event, Lesson, Student, Team, Sheet, Assignment, Test]
menu_items = dict([(m.__name__.lower(), m) for m in model_items])

self.events = EventsCrudController(model=Event, filter_bys=dict(id=self.event.id),
menu_items=menu_items, **kw)

self.lessons = LessonsCrudController(model=Lesson, filter_bys=dict(event_id=self.event.id),
menu_items=menu_items, **kw)

self.teams = TeamsCrudController(model=Team, filters=[Team.lesson_id.in_((l.id for l in self.event.lessons))],
menu_items=menu_items, **kw)

self.students = StudentsCrudController(model=Student, filters=[Student.id.in_((s.id for l in self.event.lessons for t in l.teams for s in t.students))],
menu_items=menu_items, **kw)

@expose('sauce.templates.admin_index')

self.sheets = SheetsCrudController(model=Sheet, filter_bys=dict(event_id=self.event.id),
menu_items=menu_items, **kw)

self.assignments = AssignmentsCrudController(model=Assignment, filters=[Assignment.sheet_id.in_((s.id for s in self.event.sheets))],
menu_items=menu_items, **kw)

self.tests = TestsCrudController(model=Test, filters=[Test.assignment_id.in_((a.id for s in self.event.sheets for a in s.assignments))],
menu_items=menu_items, **kw)

@expose('mako:sauce.templates.admin_index')
def index(self):
return
return dict()

0 comments on commit a1f9151

Please sign in to comment.