import sys import grok from zope.component import getUtility from zope.component.factory import Factory from zope.component.interfaces import Invalid, IFactory from zope.component import createObject from zope.exceptions import DuplicationError from zope.interface import implementedBy from waeup.csvfile import CSVFile from waeup.csvfile.interfaces import ICSVFile from waeup.interfaces import IFacultyContainer, IFaculty, IWAeUPCSVImporter from waeup.utils.importexport import CSVImporter from waeup.viewlets import (MainArea, LeftSidebar, Index, Add, Manage, FormWrapMixin) class FacultyContainer(grok.Container): """See interfaces for description. """ grok.implements(IFacultyContainer) grok.require('waeup.manageUniversity') def addFaculty(self, faculty): if not IFaculty.providedBy(faculty): raise TypeError('FacultyContainers contain only IFaculty instances') self[faculty.code] = faculty return def clear(self): keys = self.keys() for key in keys: del self[key] class FacultyContainerFactory(grok.GlobalUtility): """A factory for faculty containers. """ grok.implements(IFactory) grok.name(u'waeup.FacultyContainer') title = u"Create a new faculty container.", description = u"This factory instantiates new faculty containers." def __call__(self): return FacultyContainer() def getInterfaces(self): return implementedBy(FacultyContainer) # # CSV import stuff # class IFacultyCSVFile(ICSVFile): """A CSV file that contains faculty data. """ class FacultyCSVFile(CSVFile): """An abstraction of a CSV file containing faculties. """ grok.implements(IFacultyCSVFile) grok.provides(IFacultyCSVFile) required_fields = ['code', 'title', 'title_prefix'] class FacultyCSVImporter(CSVImporter): """Shuffle data from faculty CSV files into faculty containers. """ # Tell, what kinds of objects we connect... grok.adapts(IFacultyCSVFile, IFacultyContainer) # Tell the world, that we are an importer... grok.implements(IWAeUPCSVImporter) grok.provides(IWAeUPCSVImporter) datatype = u'Faculty Importer' def doImport(self, clear_old_data=True, overwrite=True): # CSVImporter instances have a `csvfile` and a `receiver` # object defined which refer to the CSV file and the container. for row in self.csvfile.getData(): new_item = createObject(u'waeup.Faculty') for key, val in row.items(): setattr(new_item, key, val) self.receiver.addFaculty(new_item) return class IDepartmentCSVFile(ICSVFile): """A CSV file that contains department data. """ class DepartmentCSVFile(CSVFile): """An abstraction of a CSV file containing departments. """ grok.implements(IDepartmentCSVFile) grok.provides(IDepartmentCSVFile) required_fields = ['code', 'title', 'title_prefix', 'faculty_code'] class DepartmentCSVImporter(CSVImporter): """Shuffle data from department CSV files into faculty containers. """ # Tell, what kinds of objects we connect... grok.adapts(IDepartmentCSVFile, IFacultyContainer) # Tell the world, that we are an importer... grok.implements(IWAeUPCSVImporter) grok.provides(IWAeUPCSVImporter) datatype = u'Department Importer' def doImport(self, clear_old_data=True, overwrite=True): # CSVImporter instances have a `csvfile` and a `receiver` # object defined which refer to the CSV file and the container. for row in self.csvfile.getData(): new_item = createObject(u'waeup.Department') faculty_code = row['faculty_code'] faculty = self.receiver[faculty_code] del row['faculty_code'] for key, val in row.items(): setattr(new_item, key, val) faculty.addDepartment(new_item) return class ICourseCSVFile(ICSVFile): """A CSV file that contains course data. """ class CourseCSVFile(CSVFile): """An abstraction of a CSV file containing courses. """ grok.implements(ICourseCSVFile) grok.provides(ICourseCSVFile) required_fields = ['code', 'title', 'level', 'passmark', 'credits', 'semester', 'faculty', 'department'] class CourseCSVImporter(CSVImporter): """Shuffle data from course CSV files into faculty containers. """ # Tell, what kinds of objects we connect... grok.adapts(ICourseCSVFile, IFacultyContainer) # Tell the world, that we are an importer... grok.implements(IWAeUPCSVImporter) grok.provides(IWAeUPCSVImporter) datatype = u'Course Importer' def doImport(self, clear_old_data=True, overwrite=True): # CSVImporter instances have a `csvfile` and a `receiver` # object defined which refer to the CSV file and the container. for row in self.csvfile.getData(): new_item = createObject(u'waeup.Course') faculty_code = row['faculty'] faculty = self.receiver[faculty_code] del row['faculty'] dept_code = row['department'] dept = faculty[dept_code] del row['department'] for key, val in row.items(): setattr(new_item, key, val) dept.courses.addCourse(new_item) return # # Viewing / Layout stuff... # class Content(grok.Viewlet): grok.viewletmanager(MainArea) grok.context(IFacultyContainer) grok.view(Index) def getFaculties(self): """Convinience method to create a sorted list of faculties. It provides a list of dicts with entries for all data needed by usual list templates. """ result = [] for key, val in self.context.items(): result.append(dict(id=key, name=val.title)) return result class ManageFacultyContainer(grok.Viewlet): grok.viewletmanager(MainArea) grok.context(IFacultyContainer) grok.view(Manage) grok.template('manage') def update(self): form = self.request.form if 'CANCEL' in form.keys(): self.view.redirect(self.view.url(self.context)) if not 'DELETE' in form.keys(): return fac_id = form['fac_id'] if not isinstance(fac_id, list): fac_id = [fac_id] deleted = [] for id in fac_id: try: del self.context[id] deleted.append(id) except: self.view.flash('Could not delete %s: %s: %s' % ( id, sys.exc_info()[0], sys.exc_info()[1])) if len(deleted): self.view.flash('Successfully deleted: %s' % ', '.join(deleted)) # We have to redirect to let flash messages appear immediately... self.view.redirect(self.view.url()) return class AddFacultyForm(grok.AddForm): grok.context(IFacultyContainer) form_fields = grok.AutoFields(IFaculty) label = 'Add a faculty' @grok.action('Add faculty') def addFaculty(self, **data): faculty = createObject(u'waeup.Faculty') self.applyData(faculty, **data) try: self.context.addFaculty(faculty) except DuplicationError: self.status = Invalid('The name chosen already exists ' 'in the database') return self.redirect(self.url(self.context)) class AddFaculty(FormWrapMixin, grok.Viewlet): """A viewlet that wraps the `AddFacultyForm`. """ grok.viewletmanager(MainArea) grok.context(IFacultyContainer) grok.view(Add) grok.require('waeup.manageUniversity') formview_name = 'addfacultyform' # The name of the formview we # want to be rendered in this # viewlet. class AddFacultyLink(grok.Viewlet): """A link in the left sidebar displaying 'Add faculty' """ grok.viewletmanager(LeftSidebar) grok.context(IFacultyContainer) grok.view(Index) grok.order(5) # This is so cool! This link is only displayed, when the user is # allowed to use it! grok.require('waeup.manageUniversity') def render(self): return u'
Add faculty
' class ManageFacultyLink(grok.Viewlet): """A link in the left sidebar displaying 'Manage faculty' """ grok.viewletmanager(LeftSidebar) grok.context(IFacultyContainer) grok.view(Index) grok.order(5) grok.require('waeup.manageUniversity') def render(self): return u'
Manage faculties
'