This commit is contained in:
bkfox 2015-08-19 00:43:20 +02:00
parent 8d8bc71572
commit 7a18847702
6 changed files with 107 additions and 114 deletions

View File

@ -1,7 +1,9 @@
import copy import copy
from django.contrib import admin from django.contrib import admin
import programs.models as models from django.forms import Textarea
from django.db import models
from programs.models import *
# #
@ -9,26 +11,24 @@ import programs.models as models
# #
# TODO: inherits from the corresponding admin view # TODO: inherits from the corresponding admin view
class SoundFileInline (admin.TabularInline): class SoundFileInline (admin.TabularInline):
model = models.SoundFile model = SoundFile
raw_id_fields=('parent',)
fields = ('title', 'private', 'tags', 'file', 'duration', 'fragment')
extra = 1 extra = 1
class EpisodeInline (admin.StackedInline):
model = models.Episode
extra = 0
class ScheduleInline (admin.TabularInline): class ScheduleInline (admin.TabularInline):
model = models.Schedule model = Schedule
extra = 0 extra = 1
class DiffusionInline (admin.TabularInline):
model = Diffusion
raw_id_fields=('parent',)
fields = ('parent', 'type', 'date')
extra = 1
class EventInline (admin.StackedInline):
model = models.Event
extra = 0
# #
# Parents # Parents
# #
@ -37,14 +37,13 @@ class MetadataAdmin (admin.ModelAdmin):
( None, { ( None, {
'fields': [ 'title', 'tags' ] 'fields': [ 'title', 'tags' ]
}), }),
( 'metadata', { ( None, {
'fields': [ 'date' ], 'fields': [ 'date' ],
'classes': ['collapse']
}), }),
] ]
def save_model(self, request, obj, form, change): def save_model (self, request, obj, form, change):
if not obj.author: if not obj.author:
obj.author = request.user obj.author = request.user
obj.save() obj.save()
@ -52,38 +51,31 @@ class MetadataAdmin (admin.ModelAdmin):
class PublicationAdmin (MetadataAdmin): class PublicationAdmin (MetadataAdmin):
formfield_overrides = {
models.TextField: {'widget': Textarea(attrs={'style':'width:calc(100% - 12px);'})},
}
fieldsets = copy.deepcopy(MetadataAdmin.fieldsets) fieldsets = copy.deepcopy(MetadataAdmin.fieldsets)
list_display = ('id', 'title', 'date', 'public') list_display = ('id', 'title', 'date', 'private')
list_filter = ['date', 'public'] list_filter = ['date', 'private']
search_fields = ['title', 'content'] search_fields = ['title', 'content']
def __init__ (self, *args, **kwargs): fieldsets[0][1]['fields'].insert(1, 'subtitle')
self.fieldsets[0][1]['fields'].insert(1, 'subtitle') fieldsets[0][1]['fields'] += [ 'img', 'content' ]
self.fieldsets[0][1]['fields'] += [ 'img', 'content' ] fieldsets[1][1]['fields'] += [ 'parent', 'private', 'can_comment' ] #, 'meta' ],
self.fieldsets[1][1]['fields'] += [ 'parent', 'public', 'can_comment', 'meta' ],
return super(PublicationAdmin, self).__init__(*args, **kwargs)
# #
# ModelAdmin list # ModelAdmin list
# #
#class TrackAdmin (MetadataAdmin):
# fieldsets = [
# (None, { 'fields': [ 'title', 'artist', 'version', 'tags'] } )
# ]
class SoundFileAdmin (MetadataAdmin): class SoundFileAdmin (MetadataAdmin):
fieldsets = [ fieldsets = [
(None, { 'fields': ['title', 'tags', 'file', 'embed' ] } ), (None, { 'fields': ['title', 'tags', 'file', 'embed' ] } ),
('metadata', { 'fields': ['duration', 'date', 'podcastable', 'fragment' ] } ) ('metadata', { 'fields': ['duration', 'date', 'podcastable', 'fragment' ] } )
] ]
#inlines = [ EpisodeInline ]
#inlines = [ EventInline ]
class ArticleAdmin (PublicationAdmin): class ArticleAdmin (PublicationAdmin):
fieldsets = copy.deepcopy(PublicationAdmin.fieldsets) fieldsets = copy.deepcopy(PublicationAdmin.fieldsets)
@ -91,13 +83,11 @@ class ArticleAdmin (PublicationAdmin):
fieldsets[1][1]['fields'] += ['static_page'] fieldsets[1][1]['fields'] += ['static_page']
class ProgramAdmin (PublicationAdmin): class ProgramAdmin (PublicationAdmin):
fieldsets = copy.deepcopy(PublicationAdmin.fieldsets) fieldsets = copy.deepcopy(PublicationAdmin.fieldsets)
inlines = [ EpisodeInline, ScheduleInline ] inlines = [ ScheduleInline ]
fieldsets[1][1]['fields'] += ['email', 'url', 'non_stop']
fieldsets[1][1]['fields'] += ['email', 'url']
class EpisodeAdmin (PublicationAdmin): class EpisodeAdmin (PublicationAdmin):
@ -105,15 +95,16 @@ class EpisodeAdmin (PublicationAdmin):
inlines = [ SoundFileInline ] inlines = [ SoundFileInline ]
list_filter = ['parent'] + PublicationAdmin.list_filter list_filter = ['parent'] + PublicationAdmin.list_filter
# FIXME later: when we have thousands of tracks
fieldsets[0][1]['fields'] += ['tracks'] fieldsets[0][1]['fields'] += ['tracks']
admin.site.register(models.Track) admin.site.register(Track)
admin.site.register(models.SoundFile, SoundFileAdmin) admin.site.register(SoundFile, SoundFileAdmin)
admin.site.register(models.Schedule) admin.site.register(Schedule)
admin.site.register(models.Article, ArticleAdmin) admin.site.register(Article, ArticleAdmin)
admin.site.register(models.Program, ProgramAdmin) admin.site.register(Program, ProgramAdmin)
admin.site.register(models.Episode, EpisodeAdmin) admin.site.register(Episode, EpisodeAdmin)
admin.site.register(models.Event) admin.site.register(Diffusion)

View File

@ -12,6 +12,7 @@ from django.utils.html import strip_tags
# extensions # extensions
from taggit.managers import TaggableManager from taggit.managers import TaggableManager
from sortedm2m.fields import SortedManyToManyField
import programs.settings as settings import programs.settings as settings
@ -48,7 +49,7 @@ ugettext_lazy('second and fourth')
ugettext_lazy('one on two') ugettext_lazy('one on two')
EventType = { DiffusionType = {
'diffuse': 0x01 # the diffusion is planified or done 'diffuse': 0x01 # the diffusion is planified or done
, 'cancel': 0x03 # the diffusion has been canceled from grid; useful to give , 'cancel': 0x03 # the diffusion has been canceled from grid; useful to give
# the info to the users # the info to the users
@ -107,10 +108,10 @@ class Metadata (Model):
_('date') _('date')
, default = timezone.datetime.now , default = timezone.datetime.now
) )
public = models.BooleanField( private = models.BooleanField(
_('public') _('private')
, default = False , default = False
, help_text = _('publication is public') , help_text = _('publication is private')
) )
# FIXME: add a field to specify if the element should be listed or not # FIXME: add a field to specify if the element should be listed or not
meta = models.TextField( meta = models.TextField(
@ -250,6 +251,14 @@ class Track (Model):
class SoundFile (Metadata): class SoundFile (Metadata):
def get_upload_path (self, filename):
if self.parent and self.parent.parent:
path = self.parent.parent.path
else:
path = settings.AIRCOX_SOUNDFILE_DEFAULT_DIR
return os.path.join(path, filename)
parent = models.ForeignKey( parent = models.ForeignKey(
'Episode' 'Episode'
, verbose_name = _('episode') , verbose_name = _('episode')
@ -258,7 +267,7 @@ class SoundFile (Metadata):
) )
file = models.FileField( #FIXME: filefield file = models.FileField( #FIXME: filefield
_('file') _('file')
, upload_to = lambda i, f: SoundFile.__upload_path(i,f) , upload_to = get_upload_path
) )
duration = models.TimeField( duration = models.TimeField(
_('duration') _('duration')
@ -297,14 +306,6 @@ class SoundFile (Metadata):
super(SoundFile, self).save(*args, **kwargs) super(SoundFile, self).save(*args, **kwargs)
def __upload_path (self, filename):
if self.parent and self.parent.parent:
path = self.parent.parent.path
else:
path = settings.AIRCOX_SOUNDFILE_DEFAULT_DIR
return os.path.join(path, filename)
def __str__ (self): def __str__ (self):
return str(self.id) + ': ' + self.file.name return str(self.id) + ': ' + self.file.name
@ -482,11 +483,6 @@ class Program (Publication):
, blank = True , blank = True
, null = True , null = True
) )
non_stop = models.SmallIntegerField(
_('non-stop priority')
, help_text = _('this program can be used as non-stop')
, default = -1
)
@property @property
def path (self): def path (self):
@ -526,10 +522,9 @@ class Episode (Publication):
Program Program
, verbose_name = _('parent') , verbose_name = _('parent')
) )
tracks = models.ManyToManyField( tracks = SortedManyToManyField(
Track Track
, verbose_name = _('playlist') , verbose_name = _('tracks')
, blank = True
) )
@ -539,11 +534,11 @@ class Episode (Publication):
class Event (Model): class Diffusion (Model):
""" """
Event logs and planifications. Diffusion logs and planifications.
An event is: A diffusion is:
- scheduled: when it has been generated following programs' Schedule - scheduled: when it has been generated following programs' Schedule
- planified: when it has been generated manually/ponctually or scheduled - planified: when it has been generated manually/ponctually or scheduled
""" """
@ -556,23 +551,29 @@ class Event (Model):
Program Program
) )
type = models.SmallIntegerField( type = models.SmallIntegerField(
_('type') verbose_name = _('type')
, choices = [ (y, x) for x,y in EventType.items() ] , choices = [ (y, x) for x,y in DiffusionType.items() ]
) )
date = models.DateTimeField( _('date of event start') ) date = models.DateTimeField( _('date of diffusion start') )
stream = models.SmallIntegerField( stream = models.SmallIntegerField(
_('stream') verbose_name = _('stream')
, default = 0 , default = 0
, help_text = 'stream id on which the event happens' , help_text = 'stream id on which the diffusion happens'
) )
scheduled = models.BooleanField( scheduled = models.BooleanField(
_('automated') verbose_name = _('automated')
, default = False , default = False
, help_text = 'event generated automatically' , help_text = 'diffusion generated automatically'
) )
def save (self, *args, **kwargs):
if self.parent:
self.program = self.parent.parent
super(Diffusion, self).save(*args, **kwargs)
class Meta: class Meta:
verbose_name = _('Event') verbose_name = _('Diffusion')
verbose_name_plural = _('Events') verbose_name_plural = _('Diffusions')

View File

@ -1,4 +1,5 @@
Django>=1.9.0 Django>=1.9.0
taggit taggit>=0.12.1
sortedm2m>=1.0.2

View File

@ -18,7 +18,7 @@ ensure('AIRCOX_SOUNDFILE_DEFAULT_DIR',
ensure('AIRCOX_SOUNDFILE_EXT', ensure('AIRCOX_SOUNDFILE_EXT',
('ogg','flac','wav','mp3','opus')) ('ogg','flac','wav','mp3','opus'))
# Stream for the scheduled events # Stream for the scheduled diffusions
ensure('AIRCOX_SCHEDULED_STREAM', 0) ensure('AIRCOX_SCHEDULED_STREAM', 0)

View File

@ -1,31 +1,31 @@
from django.utils import timezone from django.utils import timezone
from programs.models import Schedule, Event, Episode,\ from programs.models import Schedule, Diffusion, Episode,\
EventType DiffusionType
def scheduled_month_events (date = None, unsaved_only = False): def scheduled_month_diffusions (date = None, unsaved_only = False):
""" """
Return a list of scheduled events for the month of the given date. For the Return a list of scheduled diffusions for the month of the given date. For the
non existing events, a program attribute to the corresponding program is non existing diffusions, a program attribute to the corresponding program is
set. set.
""" """
if not date: if not date:
date = timezone.datetime.today() date = timezone.datetime.today()
schedules = Schedule.objects.all() schedules = Schedule.objects.all()
events = [] diffusions = []
for schedule in schedules: for schedule in schedules:
dates = schedule.dates_of_month() dates = schedule.dates_of_month()
for date in dates: for date in dates:
event = Event.objects \ diffusion = Diffusion.objects \
.filter(date = date, parent__parent = schedule.parent) .filter(date = date, parent__parent = schedule.parent)
if event.count(): if diffusion.count():
if not unsaved_only: if not unsaved_only:
events.append(event) diffusions.append(diffusion)
continue continue
# get episode # get episode
@ -37,16 +37,16 @@ def scheduled_month_events (date = None, unsaved_only = False):
, parent = schedule.parent ) , parent = schedule.parent )
episode = episode[0] if episode.count() else None episode = episode[0] if episode.count() else None
# make event # make diffusion
event = Event( parent = episode diffusion = Diffusion( parent = episode
, program = schedule.parent , program = schedule.parent
, type = EventType['diffuse'] , type = DiffusionType['diffuse']
, date = date , date = date
, stream = settings.AIRCOX_SCHEDULED_STREAM , stream = settings.AIRCOX_SCHEDULED_STREAM
, scheduled = True , scheduled = True
) )
event.program = schedule.program diffusion.program = schedule.program
events.append(event) diffusions.append(diffusion)
return events return diffusions

View File

@ -7,7 +7,7 @@ import programs.settings
class EventList: class DiffusionList:
type = None type = None
next = None next = None
prev = None prev = None
@ -22,29 +22,29 @@ class EventList:
def get_queryset (self): def get_queryset (self):
events = models.Event.objects; diffusions = models.Diffusion.objects;
if self.next: events = events.filter( date_end__ge = timezone.now() ) if self.next: diffusions = diffusions.filter( date_end__ge = timezone.now() )
elif self.prev: events = events.filter( date_end__le = timezone.now() ) elif self.prev: diffusions = diffusions.filter( date_end__le = timezone.now() )
else: events = events.all() else: diffusions = diffusions.all()
events = events.extra(order_by = ['date']) diffusions = diffusions.extra(order_by = ['date'])
if self.at: events = events[self.at:] if self.at: diffusions = diffusions[self.at:]
if self.count: events = events[:self.count] if self.count: diffusions = diffusions[:self.count]
self.events = events self.diffusions = diffusions
def raw_string(): def raw_string():
""" """
Return a string with events rendered as raw Return a string with diffusions rendered as raw
""" """
res = [] res = []
for event in events: for diffusion in diffusions:
r = [ dateformat.format(event.date, "Y/m/d H:i:s") r = [ dateformat.format(diffusion.date, "Y/m/d H:i:s")
, str(event.type) , str(diffusion.type)
, event.parent.file.path , diffusion.parent.file.path
, event.parent.file.url , diffusion.parent.file.url
] ]
res.push(' '.join(r)) res.push(' '.join(r))
@ -56,13 +56,13 @@ class EventList:
import json import json
res = [] res = []
for event in events: for diffusion in diffusions:
r = { r = {
'date': dateformat.format(event.date, "Y/m/d H:i:s") 'date': dateformat.format(diffusion.date, "Y/m/d H:i:s")
, 'date_end': dateformat.format(event.date_end, "Y/m/d H:i:s") , 'date_end': dateformat.format(diffusion.date_end, "Y/m/d H:i:s")
, 'type': str(event.type) , 'type': str(diffusion.type)
, 'file_path': event.parent.file.path , 'file_path': diffusion.parent.file.path
, 'file_url': event.parent.file.url , 'file_url': diffusion.parent.file.url
} }
res.push(json.dumps(r)) res.push(json.dumps(r))