source: waeup/branches/ulif-rewrite/src/waeup/university/facultycontainer.py @ 4329

Last change on this file since 4329 was 4329, checked in by uli, 16 years ago

Add importer for CSV certificate files.

  • Property svn:eol-style set to native
File size: 10.2 KB
RevLine 
[4236]1import sys
[3526]2import grok
[3912]3from zope.component import getUtility
[4079]4from zope.component.factory import Factory
5from zope.component.interfaces import Invalid, IFactory
[4161]6from zope.component import createObject
[3878]7from zope.exceptions import DuplicationError
[4079]8from zope.interface import implementedBy
[4222]9from waeup.csvfile import CSVFile
10from waeup.csvfile.interfaces import ICSVFile
[4161]11from waeup.interfaces import IFacultyContainer, IFaculty, IWAeUPCSVImporter
12from waeup.utils.importexport import CSVImporter
[4236]13from waeup.viewlets import (MainArea, LeftSidebar, Index, Add, Manage,
14                            FormWrapMixin)
[3526]15
[4222]16
[3878]17class 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]34class 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#
52class IFacultyCSVFile(ICSVFile):
53    """A CSV file that contains faculty data.
54    """
55
56class 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]63class 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]84class IDepartmentCSVFile(ICSVFile):
85    """A CSV file that contains department data.
86    """
[4161]87
[4250]88class 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]95class 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]119class ICourseCSVFile(ICSVFile):
120    """A CSV file that contains course data.
121    """
[4250]122
[4268]123class 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]131class 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]162class ICertificateCSVFile(ICSVFile):
163    """A CSV file that contains certificate data.
164    """
[4268]165
[4329]166class 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]175class 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]211class 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]227class 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]256class 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       
274class 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]287class 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]301class 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>'
Note: See TracBrowser for help on using the repository browser.