Skip to content
Snippets Groups Projects
Commit 9181e5fd authored by Branson Stephens's avatar Branson Stephens
Browse files

Fix for Issue #975, 'Versioned files displaying only newest versions in event...

Fix for Issue #975, 'Versioned files displaying only newest versions in event detail page'. To fix this, we add a file_version field to the event log. This is accessed from the VersionedFile object at the time of file-saving. That way, the correct version can always be associated with any given log message.
parent 9a47a8e8
No related branches found
No related tags found
No related merge requests found
......@@ -848,7 +848,10 @@ def eventLogToDict(log, request=None):
args=[log.event.graceid(), log.N],
request=request)
if log.filename:
filename = urlquote(log.filename)
actual_filename = log.filename
if log.file_version:
actual_filename += ',%d' % log.file_version
filename = urlquote(actual_filename)
file_uri = reverse("files",
args=[log.event.graceid(), filename],
request=request)
......@@ -906,6 +909,7 @@ class EventLogList(APIView):
uploadedFile = None
filename = None
file_version = None
if uploadedFile:
filename = uploadedFile.name
if filename.startswith("general/"):
......@@ -920,6 +924,8 @@ class EventLogList(APIView):
for chunk in uploadedFile.chunks():
fdest.write(chunk)
fdest.close()
# Ascertain the version assigned to this particular file.
file_version = fdest.version
except Exception, e:
# XXX This needs some thought.
response = Response(str(e), status=status.HTTP_400_BAD_REQUEST)
......@@ -928,7 +934,8 @@ class EventLogList(APIView):
event=event,
issuer=request.user,
comment=message,
filename=filename)
filename=filename,
file_version=file_version)
logset = event.eventlog_set.order_by("created","N")
try:
logentry.save()
......@@ -1329,9 +1336,22 @@ def download(request, graceid, filename=""):
content_type, encoding = VersionedFile.guess_mimetype(filepath)
content_type = content_type or "application/octet-stream"
# XXX encoding should probably not be ignored.
# Get a pretty filename. Just strip off version info.
# XXX This will break if you change the file-version naming convention
# (by, for instance, using a different delimiter than a comma).
try:
ind = filename.index(',')
pretty_filename = filename[:ind]
except ValueError:
pretty_filename = filename
response = HttpResponse(open(filepath, "r"), content_type=content_type)
if content_type == "application/octet-stream":
response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(filename)
#response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(filename)
response['Content-Disposition'] = 'attachment; filename=%s' % pretty_filename
else:
response['Content-Disposition'] = 'inline; filename=%s' % pretty_filename
if encoding is not None:
response['Content-Encoding'] = encoding
elif not filename:
......@@ -1484,6 +1504,7 @@ class Files(APIView):
for chunk in f.chunks():
fdest.write(chunk)
fdest.close()
file_version = fdest.version
rv = {}
# XXX this seems wobbly.
......@@ -1500,7 +1521,8 @@ class Files(APIView):
logentry = EventLog(event=event,
issuer=request.user,
comment='',
filename=filename)
filename=filename,
file_version=file_version)
try:
logentry.save()
except:
......
# -*- coding: 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 'EventLog.file_version'
db.add_column('gracedb_eventlog', 'file_version',
self.gf('django.db.models.fields.IntegerField')(null=True),
keep_default=False)
def backwards(self, orm):
# Deleting field 'EventLog.file_version'
db.delete_column('gracedb_eventlog', 'file_version')
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']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", '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']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'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']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", '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'})
},
'gracedb.approval': {
'Meta': {'object_name': 'Approval'},
'approvedEvent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gracedb.Event']"}),
'approver': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'approvingCollaboration': ('django.db.models.fields.CharField', [], {'max_length': '1'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'gracedb.coincinspiralevent': {
'Meta': {'ordering': "['-id']", 'object_name': 'CoincInspiralEvent', '_ormbases': ['gracedb.Event']},
'combined_far': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'end_time': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'end_time_ns': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'event_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['gracedb.Event']", 'unique': 'True', 'primary_key': 'True'}),
'false_alarm_rate': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'ifos': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '20'}),
'mass': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'mchirp': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'minimum_duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'snr': ('django.db.models.fields.FloatField', [], {'null': 'True'})
},
'gracedb.event': {
'Meta': {'ordering': "['-id']", 'object_name': 'Event'},
'analysisType': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'far': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'gpstime': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gracedb.Group']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'instruments': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '20'}),
'labels': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['gracedb.Label']", 'through': "orm['gracedb.Labelling']", 'symmetrical': 'False'}),
'likelihood': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'nevents': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'submitter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'uid': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '20'})
},
'gracedb.eventlog': {
'Meta': {'ordering': "['-created', '-N']", 'unique_together': "(('event', 'N'),)", 'object_name': 'EventLog'},
'N': ('django.db.models.fields.IntegerField', [], {}),
'comment': ('django.db.models.fields.TextField', [], {}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gracedb.Event']"}),
'file_version': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'filename': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'issuer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'gracedb.grbevent': {
'Meta': {'ordering': "['-id']", 'object_name': 'GrbEvent', '_ormbases': ['gracedb.Event']},
'author_ivorn': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'author_shortname': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'coord_system': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'dec': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'error_radius': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'event_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['gracedb.Event']", 'unique': 'True', 'primary_key': 'True'}),
'how_description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'how_reference_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}),
'ivorn': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'observatory_location_id': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'ra': ('django.db.models.fields.FloatField', [], {'null': 'True'})
},
'gracedb.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '20'})
},
'gracedb.label': {
'Meta': {'object_name': 'Label'},
'defaultColor': ('django.db.models.fields.CharField', [], {'default': "'black'", 'max_length': '20'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'})
},
'gracedb.labelling': {
'Meta': {'object_name': 'Labelling'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gracedb.Event']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gracedb.Label']"})
},
'gracedb.multiburstevent': {
'Meta': {'ordering': "['-id']", 'object_name': 'MultiBurstEvent', '_ormbases': ['gracedb.Event']},
'amplitude': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'bandwidth': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'central_freq': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'confidence': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'event_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['gracedb.Event']", 'unique': 'True', 'primary_key': 'True'}),
'false_alarm_rate': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'ifos': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '20'}),
'ligo_angle': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'ligo_angle_sig': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'ligo_axis_dec': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'ligo_axis_ra': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'peak_time': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'peak_time_ns': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'snr': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'start_time': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'start_time_ns': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'})
},
'gracedb.singleinspiral': {
'Gamma0': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma1': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma2': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma3': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma4': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma5': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma6': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma7': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma8': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Gamma9': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'Meta': {'object_name': 'SingleInspiral'},
'alpha': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'alpha1': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'alpha2': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'alpha3': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'alpha4': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'alpha5': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'alpha6': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'amplitude': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'bank_chisq': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'bank_chisq_dof': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'beta': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'channel': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'chi': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'chisq': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'chisq_dof': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'coa_phase': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'cont_chisq': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'cont_chisq_dof': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'eff_distance': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'end_time': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'end_time_gmst': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'end_time_ns': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'eta': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gracedb.Event']"}),
'event_duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'f_final': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ifo': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True'}),
'impulse_time': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'impulse_time_ns': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'kappa': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'mass1': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'mass2': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'mchirp': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'mtotal': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'psi0': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'psi3': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'rsqveto_duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'search': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True'}),
'sigmasq': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'snr': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'tau0': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'tau2': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'tau3': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'tau4': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'tau5': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'template_duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
'ttotal': ('django.db.models.fields.FloatField', [], {'null': 'True'})
},
'gracedb.tag': {
'Meta': {'object_name': 'Tag'},
'displayName': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
'eventlogs': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['gracedb.EventLog']", 'symmetrical': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['gracedb']
\ No newline at end of file
......@@ -231,10 +231,14 @@ class EventLog(models.Model):
comment = models.TextField(null=False)
#XXX Does this need to be indexed for better performance?
N = models.IntegerField(null=False)
file_version = models.IntegerField(null=True)
def fileurl(self):
if self.filename:
return reverse('file', args=[self.event.graceid(), self.filename])
actual_filename = self.filename
if self.file_version:
actual_filename += ',%d' % self.file_version
return reverse('file', args=[self.event.graceid(), actual_filename])
#return os.path.join(self.event.weburl(), 'private', self.filename)
else:
return None
......
......@@ -287,6 +287,7 @@ def _saveUploadedFile(event, uploadedFile):
for chunk in uploadedFile.chunks():
f.write(chunk)
f.close()
return f.version
def _createLog(request, graceid, comment, uploadedFile=None):
response = HttpResponse(mimetype='application/json')
......@@ -306,9 +307,11 @@ def _createLog(request, graceid, comment, uploadedFile=None):
issuer=request.user,
comment=comment)
if uploadedFile:
file_version = None
try:
_saveUploadedFile(event, uploadedFile)
file_version = _saveUploadedFile(event, uploadedFile)
logEntry.filename = uploadedFile.name
logEntry.file_version = file_version
except Exception, e:
rdict['error'] = "Problem saving file: %s" % str(e)
try:
......@@ -367,6 +370,8 @@ def upload(request):
for chunk in uploadedfile.chunks():
f.write(chunk)
f.close()
log.file_version = f.version
log.save()
except Exception, e:
msg = "ERROR: could not save file " + fname + " " + str(e)
log.delete()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment