From 094499e485d6f30bf31b1fb52ec0913842236237 Mon Sep 17 00:00:00 2001 From: Jordan Reedie Date: Wed, 28 Dec 2016 12:03:12 -0500 Subject: [PATCH 1/6] Keep track of the hub's clock time - moved hub heartbeat functionality into its own decorator - added field to hub model to track hub's local time - pretty print hub's last time in admin page --- src/openbadge/admin.py | 7 +++++-- src/openbadge/decorators.py | 31 ++++++++++++++++++++++++++----- src/openbadge/models.py | 3 +++ src/openbadge/permissions.py | 15 +++++++++++---- src/openbadge/views.py | 7 ++++++- 5 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/openbadge/admin.py b/src/openbadge/admin.py index 642531e..686b857 100644 --- a/src/openbadge/admin.py +++ b/src/openbadge/admin.py @@ -63,11 +63,14 @@ class MeetingInLine(admin.TabularInline): class HubInline(admin.TabularInline, GetLocalTimeMixin): model = Hub - fields = ("name", "god", "uuid", "last_seen", "ip_address", "key") - readonly_fields = ("key", 'last_seen') + fields = ("name", "god", "uuid", "last_seen", "last_hub_time", "ip_address", "key") + readonly_fields = ("key", 'last_seen', "last_hub_time") def last_seen(self, obj): return self.get_local_time(obj.last_seen_ts) + + def last_hub_time(self, obj): + return self.get_local_time(obj.last_hub_time_ts) @register(Project) diff --git a/src/openbadge/decorators.py b/src/openbadge/decorators.py index 1ed15e4..7d10cde 100644 --- a/src/openbadge/decorators.py +++ b/src/openbadge/decorators.py @@ -17,8 +17,6 @@ def is_own_project(f): is a member of the project with that ID, **OR GOD** Requires a valid hub uuid to be passed in the request header - - Updates the hub's heartbeat field """ @wraps(f) @@ -34,9 +32,6 @@ def wrap(request, project_key, *args, **kwargs): except Hub.DoesNotExist: return HttpResponseNotFound() - hub.last_seen_ts = int(time.time()) - hub.save() - hub_project_key = hub.project.key if str(hub_project_key) == str(project_key): return f(request, project_key, *args, **kwargs) @@ -46,6 +41,32 @@ def wrap(request, project_key, *args, **kwargs): return wrap +def require_hub_uuid(f): + """ + Requires a hub to pass a valid hub uuid in the request header + Updates the hub's last_seen_ts field + Stores the hub_time if provided + """ + + @wraps(f) + def wrap(request, *args, **kwargs): + hub_uuid = request.META.get("HTTP_X_HUB_UUID") + try: + hub = Hub.objects.get(uuid=hub_uuid) + except Hub.DoesNotExist: + return HttpResponseNotFound() + + hub.last_seen_ts = int(time.time()) + + hub_time = request.META.get("HTTP_X_HUB_TIME") + if hub_time is not None: + hub.last_hub_time_ts = hub_time + + hub.save() + return f(request, *args, **kwargs) + + return wrap + def app_view(f): """ensures a valid X-APPKEY has been set in a request's header""" diff --git a/src/openbadge/models.py b/src/openbadge/models.py index 2e69a66..641fed0 100644 --- a/src/openbadge/models.py +++ b/src/openbadge/models.py @@ -148,6 +148,9 @@ class Hub(BaseModel): last_seen_ts = models.DecimalField(max_digits=20, decimal_places=3, default=Decimal(0)) """The last time the hub was seen by the server (in epoch time)""" + + last_hub_time_ts = models.DecimalField(max_digits=20, decimal_places=3, default=Decimal(0)) + """ The clock time of the hub at the time of the last API request """ def get_object(self, last_update = None): if last_update: diff --git a/src/openbadge/permissions.py b/src/openbadge/permissions.py index f67db7c..031d934 100644 --- a/src/openbadge/permissions.py +++ b/src/openbadge/permissions.py @@ -16,17 +16,24 @@ def has_permission(self, request, view): class HubUuidRequired(permissions.BasePermission): """ Requires a valid Hub UUID be passed in the header - Also updates the heartbeat value for the hub that matches the UUID given + If HTTP_X_HUB_TIME is passed in the headers, updates last_hub_time """ def has_permission(self, request, view): hub_uuid = request.META.get("HTTP_X_HUB_UUID") - try: + hub_time = request.META.get("HTTP_X_HUB_TIME") + try: hub = Hub.objects.get(uuid=hub_uuid) except Hub.DoesNotExist: - return False - + return False + hub.last_seen_ts = int(time.time()) + if hub_time is not None: + hub.last_hub_time_ts = hub_time + hub.save() + return True + + diff --git a/src/openbadge/views.py b/src/openbadge/views.py index c6e32cb..4dc89a5 100644 --- a/src/openbadge/views.py +++ b/src/openbadge/views.py @@ -14,7 +14,7 @@ from rest_framework import viewsets from rest_framework.response import Response -from .decorators import app_view, is_god, is_own_project +from .decorators import app_view, is_god, is_own_project, require_hub_uuid from .models import Meeting, Project, Hub, DataFile # Chunk # ActionDataChunk, SamplesDataChunk from .models import Member @@ -134,6 +134,7 @@ def get_project(request): ########################### @is_own_project +@require_hub_uuid @app_view @api_view(['PUT', 'GET', 'POST']) def meetings(request, project_key): @@ -261,6 +262,7 @@ def post_meeting(request, project_key): ########################### @is_own_project +@require_hub_uuid @app_view @api_view(['POST']) def datafiles(request, project_key): @@ -362,6 +364,7 @@ def put_hubs(request, project_key): @is_own_project +@require_hub_uuid @api_view(['GET']) def get_hubs(request, project_key): hub_uuid = request.META.get("HTTP_X_HUB_UUID") @@ -378,6 +381,7 @@ def get_hubs(request, project_key): @is_own_project +@require_hub_uuid @is_god @api_view(['POST']) def post_hubs(request, project_key): @@ -389,6 +393,7 @@ def post_hubs(request, project_key): ######################### @is_own_project +@require_hub_uuid @app_view @api_view(['PUT', 'GET', 'POST']) def members(request, project_key): From ba91991c077cedbfa347900fdc2cf1658ae04374 Mon Sep 17 00:00:00 2001 From: Jordan Reedie Date: Fri, 30 Dec 2016 15:58:46 -0500 Subject: [PATCH 2/6] badge update logic changes: - an update to a badge cannot 'fail' now - last_audio, last_proximity, and last_seen timestamps will only update if the provided times are newer - last_voltage updates regardless - also added time_difference to admin page for hub time vs last seen time --- src/openbadge/admin.py | 7 +++++-- src/openbadge/serializers.py | 25 ++++++++++++++++--------- src/openbadge/views.py | 4 ---- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/openbadge/admin.py b/src/openbadge/admin.py index 686b857..32d1506 100644 --- a/src/openbadge/admin.py +++ b/src/openbadge/admin.py @@ -63,14 +63,17 @@ class MeetingInLine(admin.TabularInline): class HubInline(admin.TabularInline, GetLocalTimeMixin): model = Hub - fields = ("name", "god", "uuid", "last_seen", "last_hub_time", "ip_address", "key") - readonly_fields = ("key", 'last_seen', "last_hub_time") + fields = ("name", "god", "uuid", "last_seen", "last_hub_time", "time_difference_in_seconds", "ip_address", "key") + readonly_fields = ("key", 'last_seen', "last_hub_time", "time_difference_in_seconds") def last_seen(self, obj): return self.get_local_time(obj.last_seen_ts) def last_hub_time(self, obj): return self.get_local_time(obj.last_hub_time_ts) + + def time_difference_in_seconds(self, obj): + return abs(obj.last_seen_ts - obj.last_hub_time_ts) @register(Project) diff --git a/src/openbadge/serializers.py b/src/openbadge/serializers.py index a032c6f..4db4a5c 100644 --- a/src/openbadge/serializers.py +++ b/src/openbadge/serializers.py @@ -1,4 +1,5 @@ from rest_framework import serializers +import time from .models import Member, Project, Hub @@ -14,19 +15,25 @@ class Meta: def update(self, instance, validated_data): - if validated_data.get('last_audio_ts') < instance.last_audio_ts or \ - validated_data.get('last_proximity_ts') < instance.last_proximity_ts: + # if we have an older audio_ts, update it + if validated_data.get('last_audio_ts') > instance.last_audio_ts: + instance.last_audio_ts = validated_data.get('last_audio_ts', + instance.last_audio_ts) + instance.last_audio_ts_fract = validated_data.get('last_audio_ts_fract', + instance.last_audio_ts_fract) - raise serializers.ValidationError('Found newer last_audio_ts, or last_proximity_ts ' - 'in the existing Badge') + # if we have an older proximity_ts, update it + if validated_data.get('last_proximity_ts') > instance.last_proximity_ts: + instance.last_proximity_ts = validated_data.get('last_proximity_ts', instance.last_proximity_ts) - instance.last_audio_ts = validated_data.get('last_audio_ts', instance.last_audio_ts) - instance.last_audio_ts_fract = validated_data.get('last_audio_ts_fract', instance.last_audio_ts_fract) - instance.last_proximity_ts = validated_data.get('last_proximity_ts', instance.last_proximity_ts) + # if we have an older last_seen_ts, update it + if validated_data.get('last_seen_ts') > instance.last_seen_ts: + instance.last_seen_ts = time.time() + + # update voltage regardless instance.last_voltage = validated_data.get('last_voltage', instance.last_voltage) instance.save() - return instance class HubSerializer(serializers.ModelSerializer): @@ -34,7 +41,7 @@ class HubSerializer(serializers.ModelSerializer): class Meta: model = Hub - fields = ('id', 'project', 'name', 'heartbeat', + fields = ('id', 'project', 'name', 'last_seen_ts', 'god', 'uuid', 'ip_address', 'key') read_only_fields = ('id', 'project', 'name', 'heartbeat', 'key', 'god', 'uuid') diff --git a/src/openbadge/views.py b/src/openbadge/views.py index 4dc89a5..9bacb39 100644 --- a/src/openbadge/views.py +++ b/src/openbadge/views.py @@ -50,10 +50,6 @@ def retrieve(self, request, *args, **kwargs): Also update the last time the badge was seen """ badge = self.get_object() - #NOTE I don't really like doing this in the retrieve method, - # But it was by far the easiest way - badge.last_seen_ts = int(time.time()) - badge.save() serializer = self.get_serializer(badge) return Response(serializer.data) From c3e1d021a952791a6da7ccc15fe99dc788ff2cfe Mon Sep 17 00:00:00 2001 From: Jordan Reedie Date: Sat, 31 Dec 2016 10:25:05 -0500 Subject: [PATCH 3/6] use the last_seen_ts provided by hub - instead of using current server time, use time given by hub for badge's last_seen_ts allows for more accurate tracking of badges - also update last_voltage only if we have a more recent last_seen_ts, otherwise that means the last_voltage we got previously was more recent --- src/openbadge/serializers.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/openbadge/serializers.py b/src/openbadge/serializers.py index 4db4a5c..a095678 100644 --- a/src/openbadge/serializers.py +++ b/src/openbadge/serializers.py @@ -26,12 +26,10 @@ def update(self, instance, validated_data): if validated_data.get('last_proximity_ts') > instance.last_proximity_ts: instance.last_proximity_ts = validated_data.get('last_proximity_ts', instance.last_proximity_ts) - # if we have an older last_seen_ts, update it + # if we have an older last_seen_ts, update it and voltage if validated_data.get('last_seen_ts') > instance.last_seen_ts: - instance.last_seen_ts = time.time() - - # update voltage regardless - instance.last_voltage = validated_data.get('last_voltage', instance.last_voltage) + instance.last_seen_ts = validated_data.get('last_seen_ts', instance.last_seen_ts) + instance.last_voltage = validated_data.get('last_voltage', instance.last_voltage) instance.save() return instance From 8a74c794e99b1cb8836d005f92c10d62b3880a28 Mon Sep 17 00:00:00 2001 From: Jordan Reedie Date: Mon, 9 Jan 2017 12:26:17 -0500 Subject: [PATCH 4/6] Committing migrations --- .../migrations/0026_auto_20161222_2152.py | 21 +++++++++++++ src/openbadge/migrations/0027_datafile.py | 31 +++++++++++++++++++ .../migrations/0028_auto_20161226_0627.py | 21 +++++++++++++ src/openbadge/migrations/0029_datafile.py | 31 +++++++++++++++++++ .../migrations/0030_hub_last_hub_time_ts.py | 20 ++++++++++++ 5 files changed, 124 insertions(+) create mode 100644 src/openbadge/migrations/0026_auto_20161222_2152.py create mode 100644 src/openbadge/migrations/0027_datafile.py create mode 100644 src/openbadge/migrations/0028_auto_20161226_0627.py create mode 100644 src/openbadge/migrations/0029_datafile.py create mode 100644 src/openbadge/migrations/0030_hub_last_hub_time_ts.py diff --git a/src/openbadge/migrations/0026_auto_20161222_2152.py b/src/openbadge/migrations/0026_auto_20161222_2152.py new file mode 100644 index 0000000..5487ad9 --- /dev/null +++ b/src/openbadge/migrations/0026_auto_20161222_2152.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('openbadge', '0025_auto_20161222_2015'), + ] + + operations = [ + migrations.RemoveField( + model_name='datafile', + name='hub', + ), + migrations.DeleteModel( + name='DataFile', + ), + ] diff --git a/src/openbadge/migrations/0027_datafile.py b/src/openbadge/migrations/0027_datafile.py new file mode 100644 index 0000000..2759497 --- /dev/null +++ b/src/openbadge/migrations/0027_datafile.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('openbadge', '0026_auto_20161222_2152'), + ] + + operations = [ + migrations.CreateModel( + name='DataFile', + fields=[ + ('id', models.AutoField(serialize=False, primary_key=True)), + ('key', models.CharField(db_index=True, unique=True, max_length=10, blank=True)), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('date_updated', models.DateTimeField(auto_now=True)), + ('uuid', models.CharField(unique=True, max_length=64, db_index=True)), + ('data_type', models.CharField(max_length=64)), + ('last_update_timestamp', models.DecimalField(null=True, max_digits=20, decimal_places=3, blank=True)), + ('filepath', models.CharField(unique=True, max_length=65, blank=True)), + ('hub', models.ForeignKey(related_name='data', to='openbadge.Hub')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/src/openbadge/migrations/0028_auto_20161226_0627.py b/src/openbadge/migrations/0028_auto_20161226_0627.py new file mode 100644 index 0000000..7d608c3 --- /dev/null +++ b/src/openbadge/migrations/0028_auto_20161226_0627.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('openbadge', '0027_datafile'), + ] + + operations = [ + migrations.RemoveField( + model_name='datafile', + name='hub', + ), + migrations.DeleteModel( + name='DataFile', + ), + ] diff --git a/src/openbadge/migrations/0029_datafile.py b/src/openbadge/migrations/0029_datafile.py new file mode 100644 index 0000000..615d415 --- /dev/null +++ b/src/openbadge/migrations/0029_datafile.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('openbadge', '0028_auto_20161226_0627'), + ] + + operations = [ + migrations.CreateModel( + name='DataFile', + fields=[ + ('id', models.AutoField(serialize=False, primary_key=True)), + ('key', models.CharField(db_index=True, unique=True, max_length=10, blank=True)), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('date_updated', models.DateTimeField(auto_now=True)), + ('uuid', models.CharField(unique=True, max_length=64, db_index=True)), + ('data_type', models.CharField(max_length=64)), + ('last_update_timestamp', models.DecimalField(null=True, max_digits=20, decimal_places=3, blank=True)), + ('filepath', models.CharField(unique=True, max_length=65, blank=True)), + ('hub', models.ForeignKey(related_name='data', to='openbadge.Hub')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/src/openbadge/migrations/0030_hub_last_hub_time_ts.py b/src/openbadge/migrations/0030_hub_last_hub_time_ts.py new file mode 100644 index 0000000..2648353 --- /dev/null +++ b/src/openbadge/migrations/0030_hub_last_hub_time_ts.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +from decimal import Decimal + + +class Migration(migrations.Migration): + + dependencies = [ + ('openbadge', '0029_datafile'), + ] + + operations = [ + migrations.AddField( + model_name='hub', + name='last_hub_time_ts', + field=models.DecimalField(default=Decimal('0'), max_digits=20, decimal_places=3), + ), + ] From 400ea827fa8232d96e39afdcd8fc6232b03c8eef Mon Sep 17 00:00:00 2001 From: Oren Lederman Date: Mon, 9 Jan 2017 15:49:21 -0500 Subject: [PATCH 5/6] Minor bugfix in deployment script (uWSGI wouldn't start on boot) --- deploy/fabric/deploy.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deploy/fabric/deploy.py b/deploy/fabric/deploy.py index bce7d95..30d5386 100644 --- a/deploy/fabric/deploy.py +++ b/deploy/fabric/deploy.py @@ -95,6 +95,8 @@ def setup_server(): put('{0}/uwsgi-conf'.format(os.path.dirname(FILE_DIRECTORY)), '/etc/init/uwsgi.conf', use_sudo=True) sudo('[ -d `command -v systemctl` ] || systemctl daemon-reload') # run systemctl only if it exists + sudo('[ -d `command -v systemctl` ] || systemctl enable uwsgi') # run systemctl only if it exists + sudo('[ -d `command -v systemctl` ] || systemctl enable nginx') # run systemctl only if it exists sudo('mkdir -p /opt/staticfiles') sudo('chown www-data:www-data /opt/staticfiles') From ff8e164f7a4b12eb6b6b1a6c9150b2b439babef0 Mon Sep 17 00:00:00 2001 From: Oren Lederman Date: Mon, 9 Jan 2017 17:07:33 -0500 Subject: [PATCH 6/6] Moved data folder to ../data. Change DataFile model --- deploy/fabric/deploy.py | 2 ++ .../migrations/0031_auto_20170109_2145.py | 21 +++++++++++++ src/openbadge/migrations/0032_datafile.py | 31 +++++++++++++++++++ src/openbadge/models.py | 18 +++++------ src/openbadge/views.py | 13 ++++---- src/project/settings.py | 2 +- 6 files changed, 71 insertions(+), 16 deletions(-) create mode 100644 src/openbadge/migrations/0031_auto_20170109_2145.py create mode 100644 src/openbadge/migrations/0032_datafile.py diff --git a/deploy/fabric/deploy.py b/deploy/fabric/deploy.py index 30d5386..849089a 100644 --- a/deploy/fabric/deploy.py +++ b/deploy/fabric/deploy.py @@ -102,6 +102,8 @@ def setup_server(): sudo('chown www-data:www-data /opt/staticfiles') sudo('mkdir -p /opt/media') sudo('chown www-data:www-data /opt/media') + sudo('mkdir -p /opt/data') + sudo('chown www-data:www-data /opt/data') sudo('mkdir -p /var/log/django/') sudo('chown www-data:www-data /var/log/django/') diff --git a/src/openbadge/migrations/0031_auto_20170109_2145.py b/src/openbadge/migrations/0031_auto_20170109_2145.py new file mode 100644 index 0000000..fa50bd4 --- /dev/null +++ b/src/openbadge/migrations/0031_auto_20170109_2145.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('openbadge', '0030_hub_last_hub_time_ts'), + ] + + operations = [ + migrations.RemoveField( + model_name='datafile', + name='hub', + ), + migrations.DeleteModel( + name='DataFile', + ), + ] diff --git a/src/openbadge/migrations/0032_datafile.py b/src/openbadge/migrations/0032_datafile.py new file mode 100644 index 0000000..fcfc77b --- /dev/null +++ b/src/openbadge/migrations/0032_datafile.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('openbadge', '0031_auto_20170109_2145'), + ] + + operations = [ + migrations.CreateModel( + name='DataFile', + fields=[ + ('id', models.AutoField(serialize=False, primary_key=True)), + ('key', models.CharField(db_index=True, unique=True, max_length=10, blank=True)), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('date_updated', models.DateTimeField(auto_now=True)), + ('uuid', models.CharField(unique=True, max_length=64, db_index=True)), + ('data_type', models.CharField(max_length=64)), + ('last_update_timestamp', models.DecimalField(null=True, max_digits=20, decimal_places=3, blank=True)), + ('hub', models.ForeignKey(related_name='data', to='openbadge.Hub')), + ('project', models.ForeignKey(related_name='datafiles', to='openbadge.Project')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/src/openbadge/models.py b/src/openbadge/models.py index 641fed0..2df3781 100644 --- a/src/openbadge/models.py +++ b/src/openbadge/models.py @@ -310,8 +310,8 @@ def to_object(self, file): return {"metadata": meta} -class DataFile(BaseModel): +class DataFile(BaseModel): uuid = models.CharField(max_length=64, db_index=True, unique=True) """this will be a concatenation of the hub uuid and data type""" @@ -327,33 +327,33 @@ class DataFile(BaseModel): blank=True) """Log_timestamp of the last chunk received""" - filepath = models.CharField(max_length=65, unique=True, blank=True) - """Local reference to log file""" - hub = models.ForeignKey(Hub, related_name="data") """The Hub this DataFile belongs to""" + project = models.ForeignKey(Project, related_name="datafiles") + """The project this DataFile belongs to (because hub might move to a different project""" + def __unicode__(self): return unicode(self.hub.name + "_" + str(self.data_type) + "_data") def get_meta(self): """creates a json object of the metadata for this DataFile""" - return { + return { 'last_update_index': self.last_update_index, 'log_timestamp': self.last_update_timestamp, - 'hub': self.hub.name + 'hub': self.hub.name } def to_object(self, file): """Get a representation of this object for use with HTTP responses""" if file: - return { + return { "chunks": self.get_chunks(), - "metadata": self.get_meta() + "metadata": self.get_meta() } else: # is this ever going to happen? # should probably throw/log an error or something instead return { "metadata": meta } - + diff --git a/src/openbadge/views.py b/src/openbadge/views.py index 9bacb39..c89ab29 100644 --- a/src/openbadge/views.py +++ b/src/openbadge/views.py @@ -302,17 +302,18 @@ def post_datafile(request, project_key): datafile.uuid = datafile_uuid datafile.data_type = data_type datafile.hub = Hub.objects.get(uuid=hub_uuid) - folder = "".join((settings.DATA_DIR, hub.project.key)) - if not os.path.exists(folder): - os.mkdir(folder) - datafile.filepath = "{}/{}.txt".format(folder, datafile_uuid) - + datafile.project = Project.objects.get(key=project_key) + folder = os.path.join(settings.DATA_DIR,datafile.project.key) + if not os.path.exists(folder): + os.makedirs(folder) #recursive mkdir + + filepath = os.path.join(folder,datafile_uuid+".txt") # we keep track of chunks written and received as a # very basic way to ensure data integrity chunks_written = 0 - with open(datafile.filepath, 'a') as f: + with open(filepath, 'a') as f: for chunk in chunks: # storing this for the sake of if right now, # maybe useful in the future? diff --git a/src/project/settings.py b/src/project/settings.py index 3f3a502..5fffc52 100644 --- a/src/project/settings.py +++ b/src/project/settings.py @@ -244,7 +244,7 @@ SEND_POST_MEETING_SURVEY = False POST_MEETING_SURVEY_URL = "https://mit.co1.qualtrics.com/jfe/form/SV_0MR67T0jZVKamwJ" -DATA_DIR = "data/" +DATA_DIR = os.path.join(BASE_DIR, "../data") try: HOSTNAME = socket.gethostname()