diff options
Diffstat (limited to 'sbhs_server/tables')
22 files changed, 861 insertions, 0 deletions
diff --git a/sbhs_server/tables/__init__.py b/sbhs_server/tables/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sbhs_server/tables/__init__.py diff --git a/sbhs_server/tables/__init__.pyc b/sbhs_server/tables/__init__.pyc Binary files differnew file mode 100644 index 0000000..3b42411 --- /dev/null +++ b/sbhs_server/tables/__init__.pyc diff --git a/sbhs_server/tables/admin.py b/sbhs_server/tables/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/sbhs_server/tables/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/sbhs_server/tables/management/__init__.py b/sbhs_server/tables/management/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sbhs_server/tables/management/__init__.py diff --git a/sbhs_server/tables/management/__init__.pyc b/sbhs_server/tables/management/__init__.pyc Binary files differnew file mode 100644 index 0000000..409acc5 --- /dev/null +++ b/sbhs_server/tables/management/__init__.pyc diff --git a/sbhs_server/tables/management/commands/__init__.py b/sbhs_server/tables/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sbhs_server/tables/management/commands/__init__.py diff --git a/sbhs_server/tables/management/commands/__init__.pyc b/sbhs_server/tables/management/commands/__init__.pyc Binary files differnew file mode 100644 index 0000000..2bcdd35 --- /dev/null +++ b/sbhs_server/tables/management/commands/__init__.pyc diff --git a/sbhs_server/tables/management/commands/generate_checksum.py b/sbhs_server/tables/management/commands/generate_checksum.py new file mode 100644 index 0000000..5e708f0 --- /dev/null +++ b/sbhs_server/tables/management/commands/generate_checksum.py @@ -0,0 +1,33 @@ +from django.core.management.base import BaseCommand +from sbhs_server.tables.models import Experiment +import hashlib + +class Command(BaseCommand): + args = '' + help = 'Calculates checksum for unchecked experiments' + + def handle(self, *args, **options): + experiments = Experiment.objects.filter(checksum="NONE") + + for e in experiments: + try: + f = open(e.log, "r") + # If log file doesn't exist, it means experiment is not done yet. + # This takes care of that. + except: + return + + data = f.read() + f.close() + data = data.strip().split("\n") + clean_data = "" + for line in data: + columns = line.split(" ") + if len(columns) >= 6: + clean_data += (" ".join(columns[0:6]) + "\n") + + checksum = hashlib.sha1(clean_data).hexdigest() + + e.checksum = checksum + e.save() + print checksum diff --git a/sbhs_server/tables/management/commands/generate_checksum.pyc b/sbhs_server/tables/management/commands/generate_checksum.pyc Binary files differnew file mode 100644 index 0000000..36d45a7 --- /dev/null +++ b/sbhs_server/tables/management/commands/generate_checksum.pyc diff --git a/sbhs_server/tables/management/commands/initialize_machines.py b/sbhs_server/tables/management/commands/initialize_machines.py new file mode 100644 index 0000000..1987a27 --- /dev/null +++ b/sbhs_server/tables/management/commands/initialize_machines.py @@ -0,0 +1,45 @@ +from django.core.management.base import BaseCommand, CommandError +from sbhs_server import settings +from sbhs_server.tables.models import Board +from sbhs_server import helpers + +class Command(BaseCommand): + args = '' + help = 'Initializes the SBHS board data in the database' + + def handle(self, *args, **options): + previous_onlines = Board.objects.only("mid").filter(online=True) + previous_onlines = [p.mid for p in previous_onlines] + for o in settings.online_mids: + try: + Board.objects.get_or_create(mid=o) + except: + pass + + new_offlines = [] + for p in previous_onlines: + if p not in settings.online_mids: + new_offlines.append(p) + + message = "SBHS Administrator,\n\n" + message += "Following issue requires immidiate attention.\n\n" + message += "SBHS could not be connected\n" + for n in new_offlines: + message += ("MID: %d\n" % n) + message += "\nYou can check the SBHS status on http://vlabs.iitb.ac.in/sbhs/admin/." + message += " Possible correction actions are:\n" + message += "1. Run this command without brackets -> ( cd $SBHS_SERVER_ROOT; ./cron_job.sh )\n" + message += "2. If same machine comes offline multiple times, replacement of the machine is advised.\n\n\n" + message += "Regards,\nSBHS Vlabs Server Code" + + print "New offline board mids", new_offlines + subject = "SBHS Vlabs: Notice - SBHS not connected" + + if len(new_offlines) > 0: + for admin in settings.SBHS_ADMINS: + helpers.mailer.email(admin[2], subject, message) + + Board.objects.filter(mid__in=settings.online_mids).update(online=True) + Board.objects.exclude(mid__in=settings.online_mids).update(online=False) + + self.stdout.write('Boards loaded') diff --git a/sbhs_server/tables/management/commands/initialize_machines.pyc b/sbhs_server/tables/management/commands/initialize_machines.pyc Binary files differnew file mode 100644 index 0000000..cbbb123 --- /dev/null +++ b/sbhs_server/tables/management/commands/initialize_machines.pyc diff --git a/sbhs_server/tables/migrations/0001_initial.py b/sbhs_server/tables/migrations/0001_initial.py new file mode 100644 index 0000000..b6de197 --- /dev/null +++ b/sbhs_server/tables/migrations/0001_initial.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'Board' + db.create_table(u'tables_board', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('trashed_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('mid', self.gf('django.db.models.fields.IntegerField')(unique=True)), + ('online', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('updated_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + )) + db.send_create_signal(u'tables', ['Board']) + + # Adding model 'Account' + db.create_table(u'tables_account', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('password', self.gf('django.db.models.fields.CharField')(max_length=128)), + ('last_login', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('trashed_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('username', self.gf('django.db.models.fields.CharField')(unique=True, max_length=127)), + ('email', self.gf('django.db.models.fields.EmailField')(unique=True, max_length=255)), + ('is_active', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('is_admin', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('board', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['tables.Board'])), + ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('updated_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + )) + db.send_create_signal(u'tables', ['Account']) + + # Adding model 'Slot' + db.create_table(u'tables_slot', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('trashed_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('start_hour', self.gf('django.db.models.fields.IntegerField')()), + ('start_minute', self.gf('django.db.models.fields.IntegerField')()), + ('end_hour', self.gf('django.db.models.fields.IntegerField')()), + ('end_minute', self.gf('django.db.models.fields.IntegerField')()), + ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('updated_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + )) + db.send_create_signal(u'tables', ['Slot']) + + # Adding model 'Booking' + db.create_table(u'tables_booking', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('trashed_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('account', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['tables.Account'])), + ('slot', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['tables.Slot'])), + ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('updated_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + )) + db.send_create_signal(u'tables', ['Booking']) + + # Adding model 'Experiment' + db.create_table(u'tables_experiment', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('trashed_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)), + ('booking', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['tables.Booking'])), + ('log', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('checksum', self.gf('django.db.models.fields.CharField')(max_length=127)), + ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('updated_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + )) + db.send_create_signal(u'tables', ['Experiment']) + + + def backwards(self, orm): + # Deleting model 'Board' + db.delete_table(u'tables_board') + + # Deleting model 'Account' + db.delete_table(u'tables_account') + + # Deleting model 'Slot' + db.delete_table(u'tables_slot') + + # Deleting model 'Booking' + db.delete_table(u'tables_booking') + + # Deleting model 'Experiment' + db.delete_table(u'tables_experiment') + + + models = { + u'tables.account': { + 'Meta': {'object_name': 'Account'}, + 'board': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Board']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '127'}) + }, + u'tables.board': { + 'Meta': {'object_name': 'Board'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}), + 'online': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.booking': { + 'Meta': {'object_name': 'Booking'}, + 'account': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Account']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slot': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Slot']"}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.experiment': { + 'Meta': {'object_name': 'Experiment'}, + 'booking': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Booking']"}), + 'checksum': ('django.db.models.fields.CharField', [], {'max_length': '127'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'log': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.slot': { + 'Meta': {'object_name': 'Slot'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'end_hour': ('django.db.models.fields.IntegerField', [], {}), + 'end_minute': ('django.db.models.fields.IntegerField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'start_hour': ('django.db.models.fields.IntegerField', [], {}), + 'start_minute': ('django.db.models.fields.IntegerField', [], {}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['tables']
\ No newline at end of file diff --git a/sbhs_server/tables/migrations/0002_remove_experiment_checksum.py b/sbhs_server/tables/migrations/0002_remove_experiment_checksum.py new file mode 100644 index 0000000..4771abf --- /dev/null +++ b/sbhs_server/tables/migrations/0002_remove_experiment_checksum.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Deleting field 'Experiment.checksum' + db.delete_column(u'tables_experiment', 'checksum') + + + def backwards(self, orm): + # Adding field 'Experiment.checksum' + db.add_column(u'tables_experiment', 'checksum', + self.gf('django.db.models.fields.CharField')(default='0', max_length=127), + keep_default=False) + + + models = { + u'tables.account': { + 'Meta': {'object_name': 'Account'}, + 'board': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Board']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '127'}) + }, + u'tables.board': { + 'Meta': {'object_name': 'Board'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}), + 'online': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.booking': { + 'Meta': {'object_name': 'Booking'}, + 'account': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Account']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slot': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Slot']"}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.experiment': { + 'Meta': {'object_name': 'Experiment'}, + 'booking': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Booking']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'log': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.slot': { + 'Meta': {'object_name': 'Slot'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'end_hour': ('django.db.models.fields.IntegerField', [], {}), + 'end_minute': ('django.db.models.fields.IntegerField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'start_hour': ('django.db.models.fields.IntegerField', [], {}), + 'start_minute': ('django.db.models.fields.IntegerField', [], {}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['tables']
\ No newline at end of file diff --git a/sbhs_server/tables/migrations/0003_add_field_Booking_booking_date.py b/sbhs_server/tables/migrations/0003_add_field_Booking_booking_date.py new file mode 100644 index 0000000..c6c4ec1 --- /dev/null +++ b/sbhs_server/tables/migrations/0003_add_field_Booking_booking_date.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as 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 'Booking.booking_date' + db.add_column(u'tables_booking', 'booking_date', + self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2014, 5, 11, 0, 0)), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Booking.booking_date' + db.delete_column(u'tables_booking', 'booking_date') + + + models = { + u'tables.account': { + 'Meta': {'object_name': 'Account'}, + 'board': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Board']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '127'}) + }, + u'tables.board': { + 'Meta': {'object_name': 'Board'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}), + 'online': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.booking': { + 'Meta': {'object_name': 'Booking'}, + 'account': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Account']"}), + 'booking_date': ('django.db.models.fields.DateTimeField', [], {}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slot': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Slot']"}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.experiment': { + 'Meta': {'object_name': 'Experiment'}, + 'booking': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Booking']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'log': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.slot': { + 'Meta': {'object_name': 'Slot'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'end_hour': ('django.db.models.fields.IntegerField', [], {}), + 'end_minute': ('django.db.models.fields.IntegerField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'start_hour': ('django.db.models.fields.IntegerField', [], {}), + 'start_minute': ('django.db.models.fields.IntegerField', [], {}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['tables']
\ No newline at end of file diff --git a/sbhs_server/tables/migrations/0004_add_field_Experiment_checksum.py b/sbhs_server/tables/migrations/0004_add_field_Experiment_checksum.py new file mode 100644 index 0000000..7f17e89 --- /dev/null +++ b/sbhs_server/tables/migrations/0004_add_field_Experiment_checksum.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as 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 'Experiment.checksum' + db.add_column(u'tables_experiment', 'checksum', + self.gf('django.db.models.fields.CharField')(default='NONE', max_length=255), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Experiment.checksum' + db.delete_column(u'tables_experiment', 'checksum') + + + models = { + u'tables.account': { + 'Meta': {'object_name': 'Account'}, + 'board': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Board']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '127'}) + }, + u'tables.board': { + 'Meta': {'object_name': 'Board'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}), + 'online': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.booking': { + 'Meta': {'object_name': 'Booking'}, + 'account': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Account']"}), + 'booking_date': ('django.db.models.fields.DateTimeField', [], {}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slot': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Slot']"}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.experiment': { + 'Meta': {'object_name': 'Experiment'}, + 'booking': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Booking']"}), + 'checksum': ('django.db.models.fields.CharField', [], {'default': "'NONE'", 'max_length': '255'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'log': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.slot': { + 'Meta': {'object_name': 'Slot'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'end_hour': ('django.db.models.fields.IntegerField', [], {}), + 'end_minute': ('django.db.models.fields.IntegerField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'start_hour': ('django.db.models.fields.IntegerField', [], {}), + 'start_minute': ('django.db.models.fields.IntegerField', [], {}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['tables']
\ No newline at end of file diff --git a/sbhs_server/tables/migrations/0005_load_boards_data.py b/sbhs_server/tables/migrations/0005_load_boards_data.py new file mode 100644 index 0000000..8ce61a7 --- /dev/null +++ b/sbhs_server/tables/migrations/0005_load_boards_data.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models +from sbhs_server.tables.models import Board + +class Migration(SchemaMigration): + + def forwards(self, orm): + for i in xrange(1, 41): + Board.objects.create(id=i, mid=i) + + def backwards(self, orm): + Board.objects.filter(mid__in=range(1,41)).delete() + + models = { + u'tables.account': { + 'Meta': {'object_name': 'Account'}, + 'board': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Board']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '127'}) + }, + u'tables.board': { + 'Meta': {'object_name': 'Board'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}), + 'online': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.booking': { + 'Meta': {'object_name': 'Booking'}, + 'account': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Account']"}), + 'booking_date': ('django.db.models.fields.DateTimeField', [], {}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slot': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Slot']"}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.experiment': { + 'Meta': {'object_name': 'Experiment'}, + 'booking': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Booking']"}), + 'checksum': ('django.db.models.fields.CharField', [], {'default': "'NONE'", 'max_length': '255'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'log': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.slot': { + 'Meta': {'object_name': 'Slot'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'end_hour': ('django.db.models.fields.IntegerField', [], {}), + 'end_minute': ('django.db.models.fields.IntegerField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'start_hour': ('django.db.models.fields.IntegerField', [], {}), + 'start_minute': ('django.db.models.fields.IntegerField', [], {}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['tables']
\ No newline at end of file diff --git a/sbhs_server/tables/migrations/0006_load_sample_users_data.py b/sbhs_server/tables/migrations/0006_load_sample_users_data.py new file mode 100644 index 0000000..5f287ac --- /dev/null +++ b/sbhs_server/tables/migrations/0006_load_sample_users_data.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models +from sbhs_server.tables.models import Account + +class Migration(SchemaMigration): + + def forwards(self, orm): + for i in xrange(1, 41): + account = Account( + name="Sample User %d" % i, + username="suser%d" % i, + email="suser%d@os-hardware.in" % i, + board_id=i, + is_active=1 + ) + account.set_password("suser%d%d" % (i, 4229)) + account.save() + + def backwards(self, orm): + for i in xrange(1, 41): + Account.objects.filter(username="suser%d" % i).delete() + + models = { + u'tables.account': { + 'Meta': {'object_name': 'Account'}, + 'board': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Board']"}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_admin': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '127'}) + }, + u'tables.board': { + 'Meta': {'object_name': 'Board'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}), + 'online': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.booking': { + 'Meta': {'object_name': 'Booking'}, + 'account': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Account']"}), + 'booking_date': ('django.db.models.fields.DateTimeField', [], {}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slot': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Slot']"}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.experiment': { + 'Meta': {'object_name': 'Experiment'}, + 'booking': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['tables.Booking']"}), + 'checksum': ('django.db.models.fields.CharField', [], {'default': "'NONE'", 'max_length': '255'}), + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'log': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + u'tables.slot': { + 'Meta': {'object_name': 'Slot'}, + 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'end_hour': ('django.db.models.fields.IntegerField', [], {}), + 'end_minute': ('django.db.models.fields.IntegerField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'start_hour': ('django.db.models.fields.IntegerField', [], {}), + 'start_minute': ('django.db.models.fields.IntegerField', [], {}), + 'trashed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + } + } + + complete_apps = ['tables']
\ No newline at end of file diff --git a/sbhs_server/tables/migrations/__init__.py b/sbhs_server/tables/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sbhs_server/tables/migrations/__init__.py diff --git a/sbhs_server/tables/models.py b/sbhs_server/tables/models.py new file mode 100644 index 0000000..7c18298 --- /dev/null +++ b/sbhs_server/tables/models.py @@ -0,0 +1,228 @@ +from django.db import models +from django.contrib.auth.models import AbstractBaseUser +from undelete.models import TrashableMixin +import random, datetime, os +from sbhs_server.helpers import mailer, simple_encrypt +from django.contrib.auth.models import UserManager +from sbhs_server import settings +from yaksh.models import Profile +# Create your models here. + +class Board(TrashableMixin): + + mid = models.IntegerField(unique=True) + online = models.BooleanField(default=True) + + created_at = models.DateTimeField(auto_now_add=True, editable=False) + updated_at = models.DateTimeField(auto_now=True, editable=False) + + @staticmethod + def can_do_random_allotment(): + return not os.path.exists(os.path.join(settings.BASE_DIR, "WORKSHOP_MODE")) + + @staticmethod + def toggle_random_allotment(): + if Board.can_do_random_allotment(): + f = open(os.path.join(settings.BASE_DIR, "WORKSHOP_MODE"), "w") + f.close() + else: + os.remove(os.path.join(settings.BASE_DIR, "WORKSHOP_MODE")) + + @staticmethod + def allot_board(): + if Board.can_do_random_allotment(): + online_boards_count = len(settings.online_mids) + board_num = random.randrange(online_boards_count) + return settings.online_mids[board_num] + else: + last_MID = Account.objects.select_related().order_by("-id")[0].board.mid; + online_boards = sorted(settings.online_mids) + for o in online_boards: + if o > last_MID: + return o + return online_boards[0] + + def image_link(self): + return settings.WEBCAM_STATIC_DIR + "image" + str(self.mid) + ".jpeg" + + +class Account(TrashableMixin, AbstractBaseUser): + + name = models.CharField(max_length=255) + username = models.CharField(max_length=127, unique=True) + email = models.EmailField(max_length=255, unique=True) + # password = models.CharField(max_length=255) # Already covered in AbstractBaseUser + + is_active = models.BooleanField(default=False) + is_admin = models.BooleanField(default=False) + board = models.ForeignKey("Board") + + created_at = models.DateTimeField(auto_now_add=True, editable=False) + updated_at = models.DateTimeField(auto_now=True, editable=False) + + objects = UserManager() + + USERNAME_FIELD = "username" + + def get_full_name(self): + return self.name + + def get_short_name(self): + return self.name + + def send_confirmation(self): + message = """Hi,\n\nPlease visit the link """ + settings.BASE_URL + """account/confirm/""" + message = message + self.confirmation_token() + message = message + """ to confirm your account.\n\n\nRegards,\nVlabs Team""" + mailer.email(self.email, "Please confirm your account", message) + + def send_password_link(self, token): + message = """Hi,\n\nPlease visit the link """ + settings.BASE_URL + """password/edit/""" + message = message + token + message = message + """ to change your password.\n\n\nRegards,\nVlabs Team""" + mailer.email(self.email, "SBHS vlabs password reset link", message) + + def get_profile(self): + return self.profile + + + def confirmation_token(self): + return simple_encrypt.encrypt(self.email) + + +class Slot(TrashableMixin): + + start_hour = models.IntegerField() + start_minute = models.IntegerField() + + end_hour = models.IntegerField() + end_minute = models.IntegerField() + + created_at = models.DateTimeField(auto_now_add=True, editable=False) + updated_at = models.DateTimeField(auto_now=True, editable=False) + + def __str__(self): + sh = str(self.start_hour) if len(str(self.start_hour)) == 2 else "0" + str(self.start_hour) + sm = str(self.start_minute) if len(str(self.start_minute)) == 2 else "0" + str(self.start_minute) + eh = str(self.end_hour) if len(str(self.end_hour)) == 2 else "0" + str(self.end_hour) + em = str(self.end_minute) if len(str(self.end_minute)) == 2 else "0" + str(self.end_minute) + return sh + ":" + sm + " -- " + eh + ":" + em + + @staticmethod + def indices(self, other): + # These lines are irrelevant due to booking date scheme + # + # now = datetime.datetime.now() + # cur_hour = now.hour + + # s = abs(cur_hour - self.start_hour) + # s = s + 100 if self.start_hour < cur_hour else s + # o = abs(cur_hour - other.start_hour) + # o = o + 100 if other.start_hour < cur_hour else o + return self.start_hour, other.start_hour + + def __lt__(self, other): + s, o = Slot.indices(self, other) + return s < o + + def __gt__(self, other): + s, o = Slot.indices(self, other) + return s > o + + def __ne__(self, other): + s, o = Slot.indices(self, other) + return s != o + + def __eq__(self, other): + s, o = Slot.indices(self, other) + return s == o + + def __le__(self, other): + s, o = Slot.indices(self, other) + return s <= o + + def __ge__(self, other): + s, o = Slot.indices(self, other) + return s >= o + + @staticmethod + def current_slots(mid): + now = datetime.datetime.now() + slots = list(Slot.objects.filter(start_hour=now.hour, end_minute__gt=now.minute)) + bookings = Booking.objects.filter(booking_date__year=now.year, + booking_date__month=now.month, + booking_date__day=now.day, slot__in=slots, + account__board__mid=mid) + for b in bookings: + if b.slot in slots: + slots.remove(b.slot) + + return slots + + @staticmethod + def slots_now(): + now = datetime.datetime.now() + slots = list(Slot.objects.filter(start_hour=now.hour)) + return slots + + @staticmethod + def get_free_slots(mid): + now = datetime.datetime.now() + slots = list(Slot.objects.filter(start_hour__gte=now.hour)) + bookings = Booking.objects.filter(booking_date__year=now.year, + booking_date__month=now.month, + booking_date__day=now.day, slot__in=slots, + account__board__mid=mid) + for b in bookings: + if b.slot in slots: + slots.remove(b.slot) + + return sorted(slots) + + @staticmethod + def get_free_slots_on(date, mid): + now = datetime.datetime.now() + if date.strftime("%Y-%m-%d") == now.strftime("%Y-%m-%d"): + slots = list(Slot.get_free_slots(mid)) + elif date > now: + slots = list(Slot.objects.all()) + bookings = Booking.objects.filter(booking_date__year=date.year, + booking_date__month=date.month, + booking_date__day=date.day, + account__board__mid=mid) + + for b in bookings: + if b.slot in slots: + slots.remove(b.slot) + else: + slots = [] + + return sorted(slots) + + +class Booking(TrashableMixin): + + account = models.ForeignKey("Account") + slot = models.ForeignKey("Slot") + + booking_date = models.DateTimeField() + + created_at = models.DateTimeField(auto_now_add=True, editable=False) + updated_at = models.DateTimeField(auto_now=True, editable=False) + + def start_time(self): + return self.booking_date.replace(hour=self.slot.start_hour, minute=self.slot.start_minute) + + def end_time(self): + return self.booking_date.replace(hour=self.slot.end_hour, minute=self.slot.end_minute) + + +class Experiment(TrashableMixin): + + booking = models.ForeignKey("Booking") + + log = models.CharField(max_length=255) + checksum = models.CharField(max_length=255, default="NONE") + + created_at = models.DateTimeField(auto_now_add=True, editable=False) + updated_at = models.DateTimeField(auto_now=True, editable=False) diff --git a/sbhs_server/tables/models.pyc b/sbhs_server/tables/models.pyc Binary files differnew file mode 100644 index 0000000..7370f9a --- /dev/null +++ b/sbhs_server/tables/models.pyc diff --git a/sbhs_server/tables/tests.py b/sbhs_server/tables/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/sbhs_server/tables/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/sbhs_server/tables/views.py b/sbhs_server/tables/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/sbhs_server/tables/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. |