From 932ada26b1f35698a65b9df2b487d9467fd68339 Mon Sep 17 00:00:00 2001 From: gfawcett Date: Thu, 15 Jul 2010 00:54:42 +0000 Subject: [PATCH] Changed mind: each Site has exactly one Course, one Term, one Owner. Schema change. This radically simplifies the design. Access control and personalization can still be addressed through membership Groups. There can be only one Site with a given (course, term, owner) triple. git-svn-id: svn://svn.open-ils.org/ILS-Contrib/servres/trunk@912 6d9bc8c9-1ec2-4278-b937-99fde70a366f --- conifer/grahams-init-fixture.json | 2 +- ..._add_field_site_course__add_unique_site_owne.py | 205 +++++++++++++++++++++ conifer/syrup/models.py | 16 +- conifer/templates/edit_site.xhtml | 9 +- 4 files changed, 220 insertions(+), 12 deletions(-) create mode 100644 conifer/syrup/migrations/0002_auto__add_field_site_term__add_field_site_course__add_unique_site_owne.py diff --git a/conifer/grahams-init-fixture.json b/conifer/grahams-init-fixture.json index ee796a6..ec1d296 100644 --- a/conifer/grahams-init-fixture.json +++ b/conifer/grahams-init-fixture.json @@ -1 +1 @@ -[{"pk": 1, "model": "syrup.userprofile", "fields": {"last_email_notice": "2010-07-08 22:26:34", "created": "2010-07-08 22:26:34", "wants_email_notices": false, "last_modified": "2010-07-08 22:26:34", "user": 1, "ils_userid": null}}, {"pk": 1, "model": "syrup.servicedesk", "fields": {"active": true, "last_modified": "2010-07-08 22:30:22", "external_id": "", "name": "Leddy Library Reserves, Lower Level", "created": "2010-07-08 22:30:22"}}, {"pk": 1, "model": "syrup.term", "fields": {"code": "2010S", "name": "2010 Summer", "created": "2010-07-08 22:29:28", "finish": "2010-09-01", "start": "2010-05-01", "last_modified": "2010-07-08 22:29:28"}}, {"pk": 2, "model": "syrup.term", "fields": {"code": "2010F", "name": "2010 Fall", "created": "2010-07-08 22:29:50", "finish": "2010-12-31", "start": "2010-09-01", "last_modified": "2010-07-08 22:29:50"}}, {"pk": 3, "model": "syrup.term", "fields": {"code": "2011W", "name": "2011 Winter", "created": "2010-07-08 22:30:05", "finish": "2011-05-01", "start": "2011-01-01", "last_modified": "2010-07-08 22:30:05"}}, {"pk": 1, "model": "syrup.department", "fields": {"active": true, "service_desk": 1, "last_modified": "2010-07-08 22:30:34", "name": "Metaphysics", "created": "2010-07-08 22:30:34"}}, {"pk": 2, "model": "syrup.department", "fields": {"active": true, "service_desk": 1, "last_modified": "2010-07-08 22:30:44", "name": "Biology", "created": "2010-07-08 22:30:44"}}, {"pk": 3, "model": "syrup.department", "fields": {"active": true, "service_desk": 1, "last_modified": "2010-07-08 22:30:54", "name": "Computer Science", "created": "2010-07-08 22:30:54"}}, {"pk": 1, "model": "syrup.course", "fields": {"code": "99-100", "department": 1, "last_modified": "2010-07-08 22:31:24", "name": "Introduction to Thought", "created": "2010-07-08 22:31:24"}}, {"pk": 2, "model": "syrup.course", "fields": {"code": "99-200", "department": 1, "last_modified": "2010-07-08 22:31:36", "name": "Intermediate Thought", "created": "2010-07-08 22:31:36"}}, {"pk": 1, "model": "syrup.z3950target", "fields": {"name": "zed/OWA", "database": "OWA", "syntax": "USMARC", "host": "zed.concat.ca", "active": true, "port": 210}}, {"pk": 1, "model": "syrup.config", "fields": {"name": "application.title", "value": "Reserv-o-Matic"}}, {"pk": 2, "model": "syrup.config", "fields": {"name": "default.desk", "value": "1"}}] +[{"pk": 22, "model": "auth.permission", "fields": {"codename": "add_logentry", "name": "Can add log entry", "content_type": 8}}, {"pk": 23, "model": "auth.permission", "fields": {"codename": "change_logentry", "name": "Can change log entry", "content_type": 8}}, {"pk": 24, "model": "auth.permission", "fields": {"codename": "delete_logentry", "name": "Can delete log entry", "content_type": 8}}, {"pk": 4, "model": "auth.permission", "fields": {"codename": "add_group", "name": "Can add group", "content_type": 2}}, {"pk": 10, "model": "auth.permission", "fields": {"codename": "add_message", "name": "Can add message", "content_type": 4}}, {"pk": 1, "model": "auth.permission", "fields": {"codename": "add_permission", "name": "Can add permission", "content_type": 1}}, {"pk": 7, "model": "auth.permission", "fields": {"codename": "add_user", "name": "Can add user", "content_type": 3}}, {"pk": 5, "model": "auth.permission", "fields": {"codename": "change_group", "name": "Can change group", "content_type": 2}}, {"pk": 11, "model": "auth.permission", "fields": {"codename": "change_message", "name": "Can change message", "content_type": 4}}, {"pk": 2, "model": "auth.permission", "fields": {"codename": "change_permission", "name": "Can change permission", "content_type": 1}}, {"pk": 8, "model": "auth.permission", "fields": {"codename": "change_user", "name": "Can change user", "content_type": 3}}, {"pk": 6, "model": "auth.permission", "fields": {"codename": "delete_group", "name": "Can delete group", "content_type": 2}}, {"pk": 12, "model": "auth.permission", "fields": {"codename": "delete_message", "name": "Can delete message", "content_type": 4}}, {"pk": 3, "model": "auth.permission", "fields": {"codename": "delete_permission", "name": "Can delete permission", "content_type": 1}}, {"pk": 9, "model": "auth.permission", "fields": {"codename": "delete_user", "name": "Can delete user", "content_type": 3}}, {"pk": 13, "model": "auth.permission", "fields": {"codename": "add_contenttype", "name": "Can add content type", "content_type": 5}}, {"pk": 14, "model": "auth.permission", "fields": {"codename": "change_contenttype", "name": "Can change content type", "content_type": 5}}, {"pk": 15, "model": "auth.permission", "fields": {"codename": "delete_contenttype", "name": "Can delete content type", "content_type": 5}}, {"pk": 16, "model": "auth.permission", "fields": {"codename": "add_session", "name": "Can add session", "content_type": 6}}, {"pk": 17, "model": "auth.permission", "fields": {"codename": "change_session", "name": "Can change session", "content_type": 6}}, {"pk": 18, "model": "auth.permission", "fields": {"codename": "delete_session", "name": "Can delete session", "content_type": 6}}, {"pk": 19, "model": "auth.permission", "fields": {"codename": "add_site", "name": "Can add site", "content_type": 7}}, {"pk": 20, "model": "auth.permission", "fields": {"codename": "change_site", "name": "Can change site", "content_type": 7}}, {"pk": 21, "model": "auth.permission", "fields": {"codename": "delete_site", "name": "Can delete site", "content_type": 7}}, {"pk": 25, "model": "auth.permission", "fields": {"codename": "add_migrationhistory", "name": "Can add migration history", "content_type": 9}}, {"pk": 26, "model": "auth.permission", "fields": {"codename": "change_migrationhistory", "name": "Can change migration history", "content_type": 9}}, {"pk": 27, "model": "auth.permission", "fields": {"codename": "delete_migrationhistory", "name": "Can delete migration history", "content_type": 9}}, {"pk": 46, "model": "auth.permission", "fields": {"codename": "add_config", "name": "Can add config", "content_type": 16}}, {"pk": 40, "model": "auth.permission", "fields": {"codename": "add_course", "name": "Can add course", "content_type": 14}}, {"pk": 37, "model": "auth.permission", "fields": {"codename": "add_department", "name": "Can add department", "content_type": 13}}, {"pk": 52, "model": "auth.permission", "fields": {"codename": "add_group", "name": "Can add group", "content_type": 18}}, {"pk": 58, "model": "auth.permission", "fields": {"codename": "add_item", "name": "Can add item", "content_type": 20}}, {"pk": 55, "model": "auth.permission", "fields": {"codename": "add_membership", "name": "Can add membership", "content_type": 19}}, {"pk": 31, "model": "auth.permission", "fields": {"codename": "add_servicedesk", "name": "Can add service desk", "content_type": 11}}, {"pk": 49, "model": "auth.permission", "fields": {"codename": "add_site", "name": "Can add site", "content_type": 17}}, {"pk": 34, "model": "auth.permission", "fields": {"codename": "add_term", "name": "Can add term", "content_type": 12}}, {"pk": 28, "model": "auth.permission", "fields": {"codename": "add_userprofile", "name": "Can add user profile", "content_type": 10}}, {"pk": 43, "model": "auth.permission", "fields": {"codename": "add_z3950target", "name": "Can add z3950 target", "content_type": 15}}, {"pk": 47, "model": "auth.permission", "fields": {"codename": "change_config", "name": "Can change config", "content_type": 16}}, {"pk": 41, "model": "auth.permission", "fields": {"codename": "change_course", "name": "Can change course", "content_type": 14}}, {"pk": 38, "model": "auth.permission", "fields": {"codename": "change_department", "name": "Can change department", "content_type": 13}}, {"pk": 53, "model": "auth.permission", "fields": {"codename": "change_group", "name": "Can change group", "content_type": 18}}, {"pk": 59, "model": "auth.permission", "fields": {"codename": "change_item", "name": "Can change item", "content_type": 20}}, {"pk": 56, "model": "auth.permission", "fields": {"codename": "change_membership", "name": "Can change membership", "content_type": 19}}, {"pk": 32, "model": "auth.permission", "fields": {"codename": "change_servicedesk", "name": "Can change service desk", "content_type": 11}}, {"pk": 50, "model": "auth.permission", "fields": {"codename": "change_site", "name": "Can change site", "content_type": 17}}, {"pk": 35, "model": "auth.permission", "fields": {"codename": "change_term", "name": "Can change term", "content_type": 12}}, {"pk": 29, "model": "auth.permission", "fields": {"codename": "change_userprofile", "name": "Can change user profile", "content_type": 10}}, {"pk": 44, "model": "auth.permission", "fields": {"codename": "change_z3950target", "name": "Can change z3950 target", "content_type": 15}}, {"pk": 48, "model": "auth.permission", "fields": {"codename": "delete_config", "name": "Can delete config", "content_type": 16}}, {"pk": 42, "model": "auth.permission", "fields": {"codename": "delete_course", "name": "Can delete course", "content_type": 14}}, {"pk": 39, "model": "auth.permission", "fields": {"codename": "delete_department", "name": "Can delete department", "content_type": 13}}, {"pk": 54, "model": "auth.permission", "fields": {"codename": "delete_group", "name": "Can delete group", "content_type": 18}}, {"pk": 60, "model": "auth.permission", "fields": {"codename": "delete_item", "name": "Can delete item", "content_type": 20}}, {"pk": 57, "model": "auth.permission", "fields": {"codename": "delete_membership", "name": "Can delete membership", "content_type": 19}}, {"pk": 33, "model": "auth.permission", "fields": {"codename": "delete_servicedesk", "name": "Can delete service desk", "content_type": 11}}, {"pk": 51, "model": "auth.permission", "fields": {"codename": "delete_site", "name": "Can delete site", "content_type": 17}}, {"pk": 36, "model": "auth.permission", "fields": {"codename": "delete_term", "name": "Can delete term", "content_type": 12}}, {"pk": 30, "model": "auth.permission", "fields": {"codename": "delete_userprofile", "name": "Can delete user profile", "content_type": 10}}, {"pk": 45, "model": "auth.permission", "fields": {"codename": "delete_z3950target", "name": "Can delete z3950 target", "content_type": 15}}, {"pk": 1, "model": "auth.user", "fields": {"username": "graham", "first_name": "", "last_name": "", "is_active": true, "is_superuser": true, "is_staff": true, "last_login": "2010-07-09 09:20:52", "groups": [], "user_permissions": [], "password": "sha1$c1214$8cc63f8cfc851f04d1058f8448d895d0532a48ad", "email": "fawcett@uwindsor.ca", "date_joined": "2010-07-09 09:15:14"}}, {"pk": 16, "model": "contenttypes.contenttype", "fields": {"model": "config", "name": "config", "app_label": "syrup"}}, {"pk": 5, "model": "contenttypes.contenttype", "fields": {"model": "contenttype", "name": "content type", "app_label": "contenttypes"}}, {"pk": 14, "model": "contenttypes.contenttype", "fields": {"model": "course", "name": "course", "app_label": "syrup"}}, {"pk": 13, "model": "contenttypes.contenttype", "fields": {"model": "department", "name": "department", "app_label": "syrup"}}, {"pk": 2, "model": "contenttypes.contenttype", "fields": {"model": "group", "name": "group", "app_label": "auth"}}, {"pk": 18, "model": "contenttypes.contenttype", "fields": {"model": "group", "name": "group", "app_label": "syrup"}}, {"pk": 20, "model": "contenttypes.contenttype", "fields": {"model": "item", "name": "item", "app_label": "syrup"}}, {"pk": 8, "model": "contenttypes.contenttype", "fields": {"model": "logentry", "name": "log entry", "app_label": "admin"}}, {"pk": 19, "model": "contenttypes.contenttype", "fields": {"model": "membership", "name": "membership", "app_label": "syrup"}}, {"pk": 4, "model": "contenttypes.contenttype", "fields": {"model": "message", "name": "message", "app_label": "auth"}}, {"pk": 9, "model": "contenttypes.contenttype", "fields": {"model": "migrationhistory", "name": "migration history", "app_label": "south"}}, {"pk": 1, "model": "contenttypes.contenttype", "fields": {"model": "permission", "name": "permission", "app_label": "auth"}}, {"pk": 11, "model": "contenttypes.contenttype", "fields": {"model": "servicedesk", "name": "service desk", "app_label": "syrup"}}, {"pk": 6, "model": "contenttypes.contenttype", "fields": {"model": "session", "name": "session", "app_label": "sessions"}}, {"pk": 7, "model": "contenttypes.contenttype", "fields": {"model": "site", "name": "site", "app_label": "sites"}}, {"pk": 17, "model": "contenttypes.contenttype", "fields": {"model": "site", "name": "site", "app_label": "syrup"}}, {"pk": 12, "model": "contenttypes.contenttype", "fields": {"model": "term", "name": "term", "app_label": "syrup"}}, {"pk": 3, "model": "contenttypes.contenttype", "fields": {"model": "user", "name": "user", "app_label": "auth"}}, {"pk": 10, "model": "contenttypes.contenttype", "fields": {"model": "userprofile", "name": "user profile", "app_label": "syrup"}}, {"pk": 15, "model": "contenttypes.contenttype", "fields": {"model": "z3950target", "name": "z3950 target", "app_label": "syrup"}}, {"pk": "7ab9e962df78ff5840a97773342df8bf", "model": "sessions.session", "fields": {"expire_date": "2010-07-23 09:20:53", "session_data": "gAJ9cQEoVQp0ZXN0Y29va2llcQJVBndvcmtlZHEDVRJfYXV0aF91c2VyX2JhY2tlbmRxBFUpZGph\nbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmRxBVUNX2F1dGhfdXNlcl9pZHEG\nSwF1LjI2YWFjNGJiMTNlZDE1ZjlmYjQxMzZlMWJjZGIxMDAw\n"}}, {"pk": 1, "model": "sites.site", "fields": {"domain": "example.com", "name": "example.com"}}, {"pk": 1, "model": "south.migrationhistory", "fields": {"applied": "2010-07-09 13:20:26", "app_name": "syrup", "migration": "0001_initial"}}, {"pk": 2, "model": "south.migrationhistory", "fields": {"applied": "2010-07-09 13:20:26", "app_name": "syrup", "migration": "0002_auto__add_field_site_term__add_field_site_course__add_unique_site_owne"}}, {"pk": 1, "model": "syrup.userprofile", "fields": {"last_email_notice": "2010-07-08 22:26:34", "created": "2010-07-08 22:26:34", "wants_email_notices": false, "last_modified": "2010-07-08 22:26:34", "user": 1, "ils_userid": null}}, {"pk": 1, "model": "syrup.servicedesk", "fields": {"active": true, "last_modified": "2010-07-08 22:30:22", "external_id": "", "name": "Leddy Library Reserves, Lower Level", "created": "2010-07-08 22:30:22"}}, {"pk": 1, "model": "syrup.term", "fields": {"code": "2010S", "name": "2010 Summer", "created": "2010-07-08 22:29:28", "finish": "2010-09-01", "start": "2010-05-01", "last_modified": "2010-07-08 22:29:28"}}, {"pk": 2, "model": "syrup.term", "fields": {"code": "2010F", "name": "2010 Fall", "created": "2010-07-08 22:29:50", "finish": "2010-12-31", "start": "2010-09-01", "last_modified": "2010-07-08 22:29:50"}}, {"pk": 3, "model": "syrup.term", "fields": {"code": "2011W", "name": "2011 Winter", "created": "2010-07-08 22:30:05", "finish": "2011-05-01", "start": "2011-01-01", "last_modified": "2010-07-08 22:30:05"}}, {"pk": 1, "model": "syrup.department", "fields": {"active": true, "service_desk": 1, "last_modified": "2010-07-08 22:30:34", "name": "Metaphysics", "created": "2010-07-08 22:30:34"}}, {"pk": 2, "model": "syrup.department", "fields": {"active": true, "service_desk": 1, "last_modified": "2010-07-08 22:30:44", "name": "Biology", "created": "2010-07-08 22:30:44"}}, {"pk": 3, "model": "syrup.department", "fields": {"active": true, "service_desk": 1, "last_modified": "2010-07-08 22:30:54", "name": "Computer Science", "created": "2010-07-08 22:30:54"}}, {"pk": 1, "model": "syrup.course", "fields": {"code": "99-100", "department": 1, "last_modified": "2010-07-08 22:31:24", "name": "Introduction to Thought", "created": "2010-07-08 22:31:24"}}, {"pk": 2, "model": "syrup.course", "fields": {"code": "99-200", "department": 1, "last_modified": "2010-07-08 22:31:36", "name": "Intermediate Thought", "created": "2010-07-08 22:31:36"}}, {"pk": 1, "model": "syrup.z3950target", "fields": {"name": "zed/OWA", "database": "OWA", "syntax": "USMARC", "host": "zed.concat.ca", "active": true, "port": 210}}, {"pk": 1, "model": "syrup.config", "fields": {"name": "application.title", "value": "Reserv-o-Matic"}}, {"pk": 2, "model": "syrup.config", "fields": {"name": "default.desk", "value": "1"}}] diff --git a/conifer/syrup/migrations/0002_auto__add_field_site_term__add_field_site_course__add_unique_site_owne.py b/conifer/syrup/migrations/0002_auto__add_field_site_term__add_field_site_course__add_unique_site_owne.py new file mode 100644 index 0000000..edebbd6 --- /dev/null +++ b/conifer/syrup/migrations/0002_auto__add_field_site_term__add_field_site_course__add_unique_site_owne.py @@ -0,0 +1,205 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Adding field 'Site.term' + db.add_column('syrup_site', 'term', self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['syrup.Term']), keep_default=False) + + # Adding field 'Site.course' + db.add_column('syrup_site', 'course', self.gf('django.db.models.fields.related.ForeignKey')(default=1, to=orm['syrup.Course']), keep_default=False) + + # Removing M2M table for field courses on 'Site' + db.delete_table('syrup_site_courses') + + # Removing M2M table for field terms on 'Site' + db.delete_table('syrup_site_terms') + + # Adding unique constraint on 'Site', fields ['owner', 'course', 'term'] + db.create_unique('syrup_site', ['owner_id', 'course_id', 'term_id']) + + + def backwards(self, orm): + + # Deleting field 'Site.term' + db.delete_column('syrup_site', 'term_id') + + # Deleting field 'Site.course' + db.delete_column('syrup_site', 'course_id') + + # Adding M2M table for field courses on 'Site' + db.create_table('syrup_site_courses', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('site', models.ForeignKey(orm['syrup.site'], null=False)), + ('course', models.ForeignKey(orm['syrup.course'], null=False)) + )) + db.create_unique('syrup_site_courses', ['site_id', 'course_id']) + + # Adding M2M table for field terms on 'Site' + db.create_table('syrup_site_terms', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('site', models.ForeignKey(orm['syrup.site'], null=False)), + ('term', models.ForeignKey(orm['syrup.term'], null=False)) + )) + db.create_unique('syrup_site_terms', ['site_id', 'term_id']) + + # Removing unique constraint on 'Site', fields ['owner', 'course', 'term'] + db.delete_unique('syrup_site', ['owner_id', 'course_id', 'term_id']) + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'syrup.config': { + 'Meta': {'object_name': 'Config'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'value': ('django.db.models.fields.CharField', [], {'max_length': '8192'}) + }, + 'syrup.course': { + 'Meta': {'object_name': 'Course'}, + 'code': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'department': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['syrup.Department']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}) + }, + 'syrup.department': { + 'Meta': {'object_name': 'Department'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'service_desk': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['syrup.ServiceDesk']"}) + }, + 'syrup.group': { + 'Meta': {'object_name': 'Group'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'external_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '2048', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['syrup.Site']"}) + }, + 'syrup.item': { + 'Meta': {'object_name': 'Item'}, + 'author': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '8192', 'null': 'True', 'blank': 'True'}), + 'bib_id': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'fileobj': ('django.db.models.fields.files.FileField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'fileobj_mimetype': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'item_type': ('django.db.models.fields.CharField', [], {'max_length': '7'}), + 'itemtype': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '1', 'null': 'True', 'blank': 'True'}), + 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'marcxml': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'parent_heading': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['syrup.Item']", 'null': 'True', 'blank': 'True'}), + 'published': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), + 'publisher': ('django.db.models.fields.CharField', [], {'max_length': '8192', 'null': 'True', 'blank': 'True'}), + 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['syrup.Site']"}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '8192', 'db_index': 'True'}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}) + }, + 'syrup.membership': { + 'Meta': {'unique_together': "(('group', 'user'),)", 'object_name': 'Membership'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['syrup.Group']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'default': "'STUDT'", 'max_length': '6'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'syrup.servicedesk': { + 'Meta': {'object_name': 'ServiceDesk'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'external_id': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'syrup.site': { + 'Meta': {'unique_together': "(('course', 'term', 'owner'),)", 'object_name': 'Site'}, + 'access': ('django.db.models.fields.CharField', [], {'default': "'CLOSE'", 'max_length': '5'}), + 'course': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['syrup.Course']"}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'passkey': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '256', 'null': 'True', 'blank': 'True'}), + 'service_desk': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['syrup.ServiceDesk']"}), + 'term': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['syrup.Term']"}) + }, + 'syrup.term': { + 'Meta': {'object_name': 'Term'}, + 'code': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'finish': ('django.db.models.fields.DateField', [], {}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '256'}), + 'start': ('django.db.models.fields.DateField', [], {}) + }, + 'syrup.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ils_userid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'last_email_notice': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'null': 'True', 'blank': 'True'}), + 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'wants_email_notices': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}) + }, + 'syrup.z3950target': { + 'Meta': {'object_name': 'Z3950Target'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'database': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'host': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'port': ('django.db.models.fields.IntegerField', [], {'default': '210'}), + 'syntax': ('django.db.models.fields.CharField', [], {'default': "'USMARC'", 'max_length': '10'}) + } + } + + complete_apps = ['syrup'] diff --git a/conifer/syrup/models.py b/conifer/syrup/models.py index 2b30d17..8d076bf 100644 --- a/conifer/syrup/models.py +++ b/conifer/syrup/models.py @@ -144,11 +144,9 @@ class Config(m.Model): class Site(BaseModel): """A a list of materials for one (or more) course offering(s).""" - # some courses may be ad-hoc and have no code. - # TODO: constrain there is at least one course and one term (deferred). - courses = m.ManyToManyField(Course) - terms = m.ManyToManyField(Term) - owner = m.ForeignKey(User) + course = m.ForeignKey(Course) + term = m.ForeignKey(Term) + owner = m.ForeignKey(User) service_desk = m.ForeignKey(ServiceDesk) access = m.CharField(max_length=5, @@ -165,11 +163,11 @@ class Site(BaseModel): # TODO: for postgres, add UNIQUE constraint on 'passkey'. passkey = m.CharField(db_index=True, blank=True, null=True, max_length=256) + class Meta: + unique_together = (('course', 'term', 'owner')) + def __unicode__(self): - cc = '%s' % (', '.join([c.code for c in self.courses.all()])) - tt = '(%s)' % (', '.join([t.code for t in self.terms.all()])) - oo = '(%s)' % self.owner.last_name - return u'%s %s %s' % (cc, tt, oo) + return u'%s %s %s' % (self.course, self.term, self.owner) def list_display(self): if self.code: diff --git a/conifer/templates/edit_site.xhtml b/conifer/templates/edit_site.xhtml index f6d9842..2a79949 100644 --- a/conifer/templates/edit_site.xhtml +++ b/conifer/templates/edit_site.xhtml @@ -17,6 +17,11 @@ else:
${site_banner(instance)}

${title}

Edit site permissionsReturn to site page

+
+ +
${field.label} @@ -31,8 +36,8 @@ else:

General description

${field_row(form.owner)} - ${field_row(form.terms)} - ${field_row(form.courses)} + ${field_row(form.term)} + ${field_row(form.course)} ${field_row(form.service_desk)} -- 2.11.0