[4236] | 1 | import sys |
---|
[3526] | 2 | import grok |
---|
[3912] | 3 | from zope.component import getUtility |
---|
[4079] | 4 | from zope.component.factory import Factory |
---|
| 5 | from zope.component.interfaces import Invalid, IFactory |
---|
[4161] | 6 | from zope.component import createObject |
---|
[3878] | 7 | from zope.exceptions import DuplicationError |
---|
[4079] | 8 | from zope.interface import implementedBy |
---|
[4222] | 9 | from waeup.csvfile import CSVFile |
---|
| 10 | from waeup.csvfile.interfaces import ICSVFile |
---|
[4161] | 11 | from waeup.interfaces import IFacultyContainer, IFaculty, IWAeUPCSVImporter |
---|
| 12 | from waeup.utils.importexport import CSVImporter |
---|
[4236] | 13 | from waeup.viewlets import (MainArea, LeftSidebar, Index, Add, Manage, |
---|
| 14 | FormWrapMixin) |
---|
[3526] | 15 | |
---|
[4222] | 16 | |
---|
[3878] | 17 | class FacultyContainer(grok.Container): |
---|
[3912] | 18 | """See interfaces for description. |
---|
| 19 | """ |
---|
[3828] | 20 | grok.implements(IFacultyContainer) |
---|
[3884] | 21 | grok.require('waeup.manageUniversity') |
---|
[3919] | 22 | |
---|
[3878] | 23 | def addFaculty(self, faculty): |
---|
| 24 | if not IFaculty.providedBy(faculty): |
---|
| 25 | raise TypeError('FacultyContainers contain only IFaculty instances') |
---|
[4230] | 26 | self[faculty.code] = faculty |
---|
| 27 | return |
---|
[3878] | 28 | |
---|
[4161] | 29 | def clear(self): |
---|
| 30 | keys = self.keys() |
---|
| 31 | for key in keys: |
---|
| 32 | del self[key] |
---|
| 33 | |
---|
[4079] | 34 | class FacultyContainerFactory(grok.GlobalUtility): |
---|
| 35 | """A factory for faculty containers. |
---|
| 36 | """ |
---|
| 37 | grok.implements(IFactory) |
---|
| 38 | grok.name(u'waeup.FacultyContainer') |
---|
| 39 | title = u"Create a new faculty container.", |
---|
| 40 | description = u"This factory instantiates new faculty containers." |
---|
[3878] | 41 | |
---|
[4079] | 42 | def __call__(self): |
---|
| 43 | return FacultyContainer() |
---|
| 44 | |
---|
| 45 | def getInterfaces(self): |
---|
| 46 | return implementedBy(FacultyContainer) |
---|
| 47 | |
---|
[4222] | 48 | |
---|
| 49 | # |
---|
| 50 | # CSV import stuff |
---|
| 51 | # |
---|
| 52 | class IFacultyCSVFile(ICSVFile): |
---|
| 53 | """A CSV file that contains faculty data. |
---|
| 54 | """ |
---|
| 55 | |
---|
| 56 | class FacultyCSVFile(CSVFile): |
---|
| 57 | """An abstraction of a CSV file containing faculties. |
---|
| 58 | """ |
---|
| 59 | grok.implements(IFacultyCSVFile) |
---|
| 60 | grok.provides(IFacultyCSVFile) |
---|
| 61 | required_fields = ['code', 'title', 'title_prefix'] |
---|
| 62 | |
---|
[4161] | 63 | class FacultyCSVImporter(CSVImporter): |
---|
[4222] | 64 | """Shuffle data from faculty CSV files into faculty containers. |
---|
[4161] | 65 | """ |
---|
[4222] | 66 | # Tell, what kinds of objects we connect... |
---|
| 67 | grok.adapts(IFacultyCSVFile, IFacultyContainer) |
---|
| 68 | # Tell the world, that we are an importer... |
---|
[4161] | 69 | grok.implements(IWAeUPCSVImporter) |
---|
[4222] | 70 | grok.provides(IWAeUPCSVImporter) |
---|
[4161] | 71 | |
---|
[4222] | 72 | datatype = u'Faculty Importer' |
---|
| 73 | |
---|
| 74 | def doImport(self, clear_old_data=True, overwrite=True): |
---|
| 75 | # CSVImporter instances have a `csvfile` and a `receiver` |
---|
| 76 | # object defined which refer to the CSV file and the container. |
---|
| 77 | for row in self.csvfile.getData(): |
---|
[4161] | 78 | new_item = createObject(u'waeup.Faculty') |
---|
[4222] | 79 | for key, val in row.items(): |
---|
| 80 | setattr(new_item, key, val) |
---|
| 81 | self.receiver.addFaculty(new_item) |
---|
[4161] | 82 | return |
---|
| 83 | |
---|
[4250] | 84 | class IDepartmentCSVFile(ICSVFile): |
---|
| 85 | """A CSV file that contains department data. |
---|
| 86 | """ |
---|
[4161] | 87 | |
---|
[4250] | 88 | class DepartmentCSVFile(CSVFile): |
---|
[4269] | 89 | """An abstraction of a CSV file containing departments. |
---|
[4250] | 90 | """ |
---|
| 91 | grok.implements(IDepartmentCSVFile) |
---|
| 92 | grok.provides(IDepartmentCSVFile) |
---|
| 93 | required_fields = ['code', 'title', 'title_prefix', 'faculty_code'] |
---|
[4222] | 94 | |
---|
[4250] | 95 | class DepartmentCSVImporter(CSVImporter): |
---|
| 96 | """Shuffle data from department CSV files into faculty containers. |
---|
| 97 | """ |
---|
| 98 | # Tell, what kinds of objects we connect... |
---|
| 99 | grok.adapts(IDepartmentCSVFile, IFacultyContainer) |
---|
| 100 | # Tell the world, that we are an importer... |
---|
| 101 | grok.implements(IWAeUPCSVImporter) |
---|
| 102 | grok.provides(IWAeUPCSVImporter) |
---|
[4222] | 103 | |
---|
[4250] | 104 | datatype = u'Department Importer' |
---|
| 105 | |
---|
| 106 | def doImport(self, clear_old_data=True, overwrite=True): |
---|
| 107 | # CSVImporter instances have a `csvfile` and a `receiver` |
---|
| 108 | # object defined which refer to the CSV file and the container. |
---|
| 109 | for row in self.csvfile.getData(): |
---|
| 110 | new_item = createObject(u'waeup.Department') |
---|
| 111 | faculty_code = row['faculty_code'] |
---|
| 112 | faculty = self.receiver[faculty_code] |
---|
| 113 | del row['faculty_code'] |
---|
| 114 | for key, val in row.items(): |
---|
| 115 | setattr(new_item, key, val) |
---|
| 116 | faculty.addDepartment(new_item) |
---|
| 117 | return |
---|
| 118 | |
---|
[4268] | 119 | class ICourseCSVFile(ICSVFile): |
---|
| 120 | """A CSV file that contains course data. |
---|
| 121 | """ |
---|
[4250] | 122 | |
---|
[4268] | 123 | class CourseCSVFile(CSVFile): |
---|
| 124 | """An abstraction of a CSV file containing courses. |
---|
| 125 | """ |
---|
| 126 | grok.implements(ICourseCSVFile) |
---|
| 127 | grok.provides(ICourseCSVFile) |
---|
| 128 | required_fields = ['code', 'title', 'level', 'passmark', 'credits', |
---|
| 129 | 'semester', 'faculty', 'department'] |
---|
[4250] | 130 | |
---|
[4268] | 131 | class CourseCSVImporter(CSVImporter): |
---|
| 132 | """Shuffle data from course CSV files into faculty containers. |
---|
| 133 | """ |
---|
| 134 | # Tell, what kinds of objects we connect... |
---|
| 135 | grok.adapts(ICourseCSVFile, IFacultyContainer) |
---|
| 136 | # Tell the world, that we are an importer... |
---|
| 137 | grok.implements(IWAeUPCSVImporter) |
---|
| 138 | grok.provides(IWAeUPCSVImporter) |
---|
[4250] | 139 | |
---|
[4268] | 140 | datatype = u'Course Importer' |
---|
| 141 | |
---|
| 142 | def doImport(self, clear_old_data=True, overwrite=True): |
---|
| 143 | # CSVImporter instances have a `csvfile` and a `receiver` |
---|
| 144 | # object defined which refer to the CSV file and the container. |
---|
| 145 | for row in self.csvfile.getData(): |
---|
[4279] | 146 | |
---|
[4268] | 147 | new_item = createObject(u'waeup.Course') |
---|
[4279] | 148 | |
---|
[4268] | 149 | faculty_code = row['faculty'] |
---|
| 150 | faculty = self.receiver[faculty_code] |
---|
[4279] | 151 | del row['faculty'] |
---|
| 152 | |
---|
[4268] | 153 | dept_code = row['department'] |
---|
| 154 | dept = faculty[dept_code] |
---|
[4279] | 155 | del row['department'] |
---|
| 156 | |
---|
[4268] | 157 | for key, val in row.items(): |
---|
| 158 | setattr(new_item, key, val) |
---|
[4279] | 159 | dept.courses.addCourse(new_item) |
---|
[4268] | 160 | return |
---|
| 161 | |
---|
[4329] | 162 | class ICertificateCSVFile(ICSVFile): |
---|
| 163 | """A CSV file that contains certificate data. |
---|
| 164 | """ |
---|
[4268] | 165 | |
---|
[4329] | 166 | class CertificateCSVFile(CSVFile): |
---|
| 167 | """An abstraction of a CSV file containing certificates. |
---|
| 168 | """ |
---|
| 169 | grok.implements(ICertificateCSVFile) |
---|
| 170 | grok.provides(ICertificateCSVFile) |
---|
| 171 | required_fields = ['code', 'title', 'faculty_code', 'department_code', |
---|
| 172 | 'category', 'study_mode', 'start_level', 'end_level', |
---|
| 173 | 'm_prefix', 'max_pass', 'application_category'] |
---|
[4268] | 174 | |
---|
[4329] | 175 | class CertificateCSVImporter(CSVImporter): |
---|
| 176 | """Shuffle data from certificate CSV files into faculty containers. |
---|
| 177 | """ |
---|
| 178 | # Tell, what kinds of objects we connect... |
---|
| 179 | grok.adapts(ICertificateCSVFile, IFacultyContainer) |
---|
| 180 | # Tell the world, that we are an importer... |
---|
| 181 | grok.implements(IWAeUPCSVImporter) |
---|
| 182 | grok.provides(IWAeUPCSVImporter) |
---|
| 183 | |
---|
| 184 | datatype = u'Certificate Importer' |
---|
| 185 | |
---|
| 186 | def doImport(self, clear_old_data=True, overwrite=True): |
---|
| 187 | # CSVImporter instances have a `csvfile` and a `receiver` |
---|
| 188 | # object defined which refer to the CSV file and the container. |
---|
| 189 | for row in self.csvfile.getData(): |
---|
| 190 | |
---|
| 191 | new_item = createObject(u'waeup.Certificate') |
---|
| 192 | |
---|
| 193 | faculty_code = row['faculty_code'] |
---|
| 194 | faculty = self.receiver[faculty_code] |
---|
| 195 | del row['faculty_code'] |
---|
| 196 | |
---|
| 197 | dept_code = row['department_code'] |
---|
| 198 | dept = faculty[dept_code] |
---|
| 199 | del row['department_code'] |
---|
| 200 | |
---|
| 201 | for key, val in row.items(): |
---|
| 202 | setattr(new_item, key, val) |
---|
| 203 | dept.certificates.addCertificate(new_item) |
---|
| 204 | return |
---|
| 205 | |
---|
| 206 | |
---|
| 207 | |
---|
[3912] | 208 | # |
---|
| 209 | # Viewing / Layout stuff... |
---|
| 210 | # |
---|
[3878] | 211 | class Content(grok.Viewlet): |
---|
| 212 | grok.viewletmanager(MainArea) |
---|
| 213 | grok.context(IFacultyContainer) |
---|
| 214 | grok.view(Index) |
---|
| 215 | |
---|
| 216 | def getFaculties(self): |
---|
| 217 | """Convinience method to create a sorted list of faculties. |
---|
| 218 | |
---|
| 219 | It provides a list of dicts with entries for all data needed by |
---|
| 220 | usual list templates. |
---|
| 221 | """ |
---|
| 222 | result = [] |
---|
| 223 | for key, val in self.context.items(): |
---|
[4132] | 224 | result.append(dict(id=key, name=val.title)) |
---|
[3878] | 225 | return result |
---|
| 226 | |
---|
[4236] | 227 | class ManageFacultyContainer(grok.Viewlet): |
---|
| 228 | grok.viewletmanager(MainArea) |
---|
| 229 | grok.context(IFacultyContainer) |
---|
| 230 | grok.view(Manage) |
---|
| 231 | grok.template('manage') |
---|
| 232 | |
---|
| 233 | def update(self): |
---|
| 234 | form = self.request.form |
---|
| 235 | if 'CANCEL' in form.keys(): |
---|
| 236 | self.view.redirect(self.view.url(self.context)) |
---|
| 237 | if not 'DELETE' in form.keys(): |
---|
| 238 | return |
---|
| 239 | fac_id = form['fac_id'] |
---|
| 240 | if not isinstance(fac_id, list): |
---|
| 241 | fac_id = [fac_id] |
---|
| 242 | deleted = [] |
---|
| 243 | for id in fac_id: |
---|
| 244 | try: |
---|
| 245 | del self.context[id] |
---|
| 246 | deleted.append(id) |
---|
| 247 | except: |
---|
| 248 | self.view.flash('Could not delete %s: %s: %s' % ( |
---|
| 249 | id, sys.exc_info()[0], sys.exc_info()[1])) |
---|
| 250 | if len(deleted): |
---|
| 251 | self.view.flash('Successfully deleted: %s' % ', '.join(deleted)) |
---|
| 252 | # We have to redirect to let flash messages appear immediately... |
---|
| 253 | self.view.redirect(self.view.url()) |
---|
| 254 | return |
---|
| 255 | |
---|
[3878] | 256 | class AddFacultyForm(grok.AddForm): |
---|
| 257 | grok.context(IFacultyContainer) |
---|
| 258 | form_fields = grok.AutoFields(IFaculty) |
---|
[3884] | 259 | label = 'Add a faculty' |
---|
[3878] | 260 | |
---|
| 261 | @grok.action('Add faculty') |
---|
| 262 | def addFaculty(self, **data): |
---|
[4161] | 263 | faculty = createObject(u'waeup.Faculty') |
---|
[3878] | 264 | self.applyData(faculty, **data) |
---|
| 265 | try: |
---|
| 266 | self.context.addFaculty(faculty) |
---|
| 267 | except DuplicationError: |
---|
| 268 | self.status = Invalid('The name chosen already exists ' |
---|
| 269 | 'in the database') |
---|
| 270 | return |
---|
| 271 | self.redirect(self.url(self.context)) |
---|
| 272 | |
---|
[3910] | 273 | |
---|
| 274 | class AddFaculty(FormWrapMixin, grok.Viewlet): |
---|
[3878] | 275 | """A viewlet that wraps the `AddFacultyForm`. |
---|
| 276 | """ |
---|
| 277 | grok.viewletmanager(MainArea) |
---|
| 278 | grok.context(IFacultyContainer) |
---|
| 279 | grok.view(Add) |
---|
| 280 | grok.require('waeup.manageUniversity') |
---|
| 281 | |
---|
[3910] | 282 | formview_name = 'addfacultyform' # The name of the formview we |
---|
| 283 | # want to be rendered in this |
---|
| 284 | # viewlet. |
---|
[3884] | 285 | |
---|
[3910] | 286 | |
---|
[3884] | 287 | class AddFacultyLink(grok.Viewlet): |
---|
| 288 | """A link in the left sidebar displaying 'Add faculty' |
---|
| 289 | """ |
---|
| 290 | grok.viewletmanager(LeftSidebar) |
---|
| 291 | grok.context(IFacultyContainer) |
---|
| 292 | grok.view(Index) |
---|
| 293 | grok.order(5) |
---|
| 294 | # This is so cool! This link is only displayed, when the user is |
---|
| 295 | # allowed to use it! |
---|
| 296 | grok.require('waeup.manageUniversity') |
---|
| 297 | |
---|
| 298 | def render(self): |
---|
| 299 | return u'<div class="portlet"><a href="add">Add faculty</a></div>' |
---|
[4161] | 300 | |
---|
[4236] | 301 | class ManageFacultyLink(grok.Viewlet): |
---|
| 302 | """A link in the left sidebar displaying 'Manage faculty' |
---|
| 303 | """ |
---|
| 304 | grok.viewletmanager(LeftSidebar) |
---|
| 305 | grok.context(IFacultyContainer) |
---|
| 306 | grok.view(Index) |
---|
| 307 | grok.order(5) |
---|
| 308 | grok.require('waeup.manageUniversity') |
---|
| 309 | |
---|
| 310 | def render(self): |
---|
| 311 | return u'<div class="portlet"><a href="manage">Manage faculties</a></div>' |
---|