Skip to content

Commit 7bc8e04

Browse files
committed
Added model UrlResource with FK to Room
This will make it easier to support audio and video streaming links which vary by meeting, but are fixed by Room. Also added migrations, resource, admin support, supporting methods, and a bit of refactoring. - Legacy-Id: 11644
1 parent 14e97a7 commit 7bc8e04

5 files changed

Lines changed: 141 additions & 16 deletions

File tree

ietf/meeting/admin.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
from django.contrib import admin
22

33
from ietf.meeting.models import (Meeting, Room, Session, TimeSlot, Constraint, Schedule,
4-
SchedTimeSessAssignment, ResourceAssociation, FloorPlan)
4+
SchedTimeSessAssignment, ResourceAssociation, FloorPlan, UrlResource)
5+
6+
7+
class UrlResourceAdmin(admin.ModelAdmin):
8+
list_display = ['name', 'room', 'url', ]
9+
raw_id_fields = ['room', ]
10+
admin.site.register(UrlResource, UrlResourceAdmin)
11+
12+
class UrlResourceInline(admin.TabularInline):
13+
model = UrlResource
514

615
class RoomAdmin(admin.ModelAdmin):
716
list_display = ["id", "meeting", "name", "capacity", "functional_name", "x1", "y1", "x2", "y2", ]
817
list_filter = ["meeting"]
18+
inlines = [UrlResourceInline, ]
919
ordering = ["-meeting"]
1020

1121
admin.site.register(Room, RoomAdmin)
@@ -97,7 +107,7 @@ class SchedTimeSessAssignmentAdmin(admin.ModelAdmin):
97107

98108

99109
class ResourceAssociationAdmin(admin.ModelAdmin):
100-
list_display = ["desc", "icon", "desc", ]
110+
list_display = ["name", "icon", "desc", ]
101111
admin.site.register(ResourceAssociation, ResourceAssociationAdmin)
102112

103113
class FloorPlanAdmin(admin.ModelAdmin):
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from django.db import models, migrations
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('name', '0013_add_group_type_verbose_name_data'),
11+
('meeting', '0026_add_floorplan_data'),
12+
]
13+
14+
operations = [
15+
migrations.CreateModel(
16+
name='UrlResource',
17+
fields=[
18+
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
19+
('url', models.URLField(null=True, blank=True)),
20+
('name', models.ForeignKey(to='name.RoomResourceName')),
21+
('room', models.ForeignKey(to='meeting.Room')),
22+
],
23+
options={
24+
},
25+
bases=(models.Model,),
26+
),
27+
]
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import unicode_literals
3+
4+
from django.db import migrations
5+
6+
rooms = [
7+
("Bellevue", "http://ietf96streaming.dnsalias.net/ietf/ietf961.m3u"),
8+
("Charlottenburg I", "http://ietf96streaming.dnsalias.net/ietf/ietf962.m3u"),
9+
("Charlottenburg II/III", "http://ietf96streaming.dnsalias.net/ietf/ietf963.m3u"),
10+
("Lincke", "http://ietf96streaming.dnsalias.net/ietf/ietf964.m3u"),
11+
("Potsdam I", "http://ietf96streaming.dnsalias.net/ietf/ietf965.m3u"),
12+
("Potsdam II", "http://ietf96streaming.dnsalias.net/ietf/ietf966.m3u"),
13+
("Potsdam III", "http://ietf96streaming.dnsalias.net/ietf/ietf967.m3u"),
14+
("Schoeneberg", "http://ietf96streaming.dnsalias.net/ietf/ietf968.m3u"),
15+
("Tiergarten", "http://ietf96streaming.dnsalias.net/ietf/ietf969.m3u"),
16+
]
17+
18+
def forward(apps, schema_editor):
19+
Room = apps.get_model('meeting','Room')
20+
Meeting = apps.get_model('meeting','Meeting')
21+
UrlResource = apps.get_model('meeting','UrlResource')
22+
RoomResourceName = apps.get_model('name','RoomResourceName')
23+
24+
meeting = Meeting.objects.get(number='96')
25+
26+
audiostream, _ = RoomResourceName.objects.get_or_create(slug='audiostream', name='Audio Stream', desc='Audio streaming support')
27+
28+
for item in rooms:
29+
name, url = item
30+
try:
31+
room = Room.objects.get(name=name, meeting=meeting)
32+
urlres, _ = UrlResource.objects.get_or_create(name=audiostream, room=room, url=url)
33+
except Room.DoesNotExist:
34+
import sys
35+
sys.stderr.write("\nNo such room: %s" % name)
36+
37+
def backward(apps, schema_editor):
38+
pass
39+
40+
class Migration(migrations.Migration):
41+
42+
dependencies = [
43+
('meeting', '0027_urlresource'),
44+
]
45+
46+
operations = [
47+
migrations.RunPython(forward,backward)
48+
]

ietf/meeting/models.py

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,6 @@ class Meta:
280280

281281
class ResourceAssociation(models.Model):
282282
name = models.ForeignKey(RoomResourceName)
283-
#url = models.UrlField() # not sure what this was for.
284283
icon = models.CharField(max_length=64) # icon to be found in /static/img
285284
desc = models.CharField(max_length=256)
286285

@@ -344,7 +343,7 @@ def json_dict(self, host_scheme):
344343
'name': self.name,
345344
'capacity': self.capacity,
346345
}
347-
346+
# floorplan support
348347
def left(self):
349348
return min(self.x1, self.x2) if (self.x1 and self.x2) else 0
350349
def top(self):
@@ -361,9 +360,24 @@ def functional_display_name(self):
361360
if self.functional_name[0].isdigit():
362361
return ""
363362
return self.functional_name
363+
# audio stream support
364+
def audio_stream_url(self):
365+
urlresource = self.urlresource_set.filter(name_id='audiostream').first()
366+
return urlresource.url if urlresource else None
367+
def video_stream_url(self):
368+
urlresource = self.urlresource_set.filter(name_id__in=['meetecho', ]).first()
369+
return urlresource.url if urlresource else None
370+
#
364371
class Meta:
365372
ordering = ["-meeting", "name"]
366373

374+
375+
class UrlResource(models.Model):
376+
"For things like audio stream urls, meetecho stream urls"
377+
name = models.ForeignKey(RoomResourceName)
378+
room = models.ForeignKey(Room)
379+
url = models.URLField(null=True, blank=True)
380+
367381
def floorplan_path(instance, filename):
368382
root, ext = os.path.splitext(filename)
369383
return u"%s/floorplan-%s-%s%s" % (settings.FLOORPLAN_MEDIA_DIR, instance.meeting.number, xslugify(instance.name), ext)
@@ -373,6 +387,9 @@ class FloorPlan(models.Model):
373387
meeting = models.ForeignKey(Meeting)
374388
order = models.SmallIntegerField()
375389
image = models.ImageField(storage=NoLocationMigrationFileSystemStorage(), upload_to=floorplan_path, blank=True, default=None)
390+
#
391+
def __unicode__(self):
392+
return 'floorplan-%s-%s' % (self.meeting.number, xslugify(self.name))
376393

377394
# === Schedules, Sessions, Timeslots and Assignments ===========================
378395

@@ -423,6 +440,7 @@ def __unicode__(self):
423440
location = "(no location)"
424441

425442
return u"%s: %s-%s %s, %s" % (self.meeting.number, self.time.strftime("%m-%d %H:%M"), (self.time + self.duration).strftime("%H:%M"), self.name, location)
443+
426444
def end_time(self):
427445
return self.time + self.duration
428446

@@ -452,26 +470,28 @@ def get_functional_location(self):
452470
name_parts.append(location)
453471
return ' - '.join(name_parts)
454472

455-
@property
456473
def tz(self):
457-
if self.meeting.time_zone:
458-
return pytz.timezone(self.meeting.time_zone)
459-
else:
460-
return None
474+
if not hasattr(self, '_cached_tz'):
475+
if self.meeting.time_zone:
476+
self._cached_tz = pytz.timezone(self.meeting.time_zone)
477+
else:
478+
self._cached_tz = None
479+
return self._cached_tz
480+
461481
def tzname(self):
462-
if self.tz:
463-
return self.tz.tzname(self.time)
482+
if self.tz():
483+
return self.tz().tzname(self.time)
464484
else:
465485
return ""
466486
def utc_start_time(self):
467-
if self.tz:
468-
local_start_time = self.tz.localize(self.time)
487+
if self.tz():
488+
local_start_time = self.tz().localize(self.time)
469489
return local_start_time.astimezone(pytz.utc)
470490
else:
471491
return None
472492
def utc_end_time(self):
473-
if self.tz:
474-
local_end_time = self.tz.localize(self.end_time())
493+
if self.tz():
494+
local_end_time = self.tz().localize(self.end_time())
475495
return local_end_time.astimezone(pytz.utc)
476496
else:
477497
return None

ietf/meeting/resources.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
from ietf import api
99

1010
from ietf.meeting.models import ( Meeting, ResourceAssociation, Constraint, Room, Schedule, Session,
11-
TimeSlot, SchedTimeSessAssignment, SessionPresentation, FloorPlan )
11+
TimeSlot, SchedTimeSessAssignment, SessionPresentation, FloorPlan,
12+
UrlResource)
1213

1314
from ietf.name.resources import MeetingTypeNameResource
1415
class MeetingResource(ModelResource):
@@ -252,3 +253,22 @@ class Meta:
252253
}
253254
api.meeting.register(SessionPresentationResource())
254255

256+
257+
258+
from ietf.name.resources import RoomResourceNameResource
259+
class UrlResourceResource(ModelResource):
260+
name = ToOneField(RoomResourceNameResource, 'name')
261+
room = ToOneField(RoomResource, 'room')
262+
class Meta:
263+
queryset = UrlResource.objects.all()
264+
serializer = api.Serializer()
265+
cache = SimpleCache()
266+
#resource_name = 'urlresource'
267+
filtering = {
268+
"id": ALL,
269+
"url": ALL,
270+
"name": ALL_WITH_RELATIONS,
271+
"room": ALL_WITH_RELATIONS,
272+
}
273+
api.meeting.register(UrlResourceResource())
274+

0 commit comments

Comments
 (0)