From 7a18847702ea9015e3af472183197e126694e46f Mon Sep 17 00:00:00 2001 From: bkfox Date: Wed, 19 Aug 2015 00:43:20 +0200 Subject: [PATCH] admin --- programs/admin.py | 77 +++++++++++++++++---------------------- programs/models.py | 67 +++++++++++++++++----------------- programs/requirements.txt | 3 +- programs/settings.py | 2 +- programs/utils.py | 30 +++++++-------- programs/views.py | 42 ++++++++++----------- 6 files changed, 107 insertions(+), 114 deletions(-) diff --git a/programs/admin.py b/programs/admin.py index 2cbf434..f004788 100755 --- a/programs/admin.py +++ b/programs/admin.py @@ -1,7 +1,9 @@ import copy 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 class SoundFileInline (admin.TabularInline): - model = models.SoundFile + model = SoundFile + raw_id_fields=('parent',) + fields = ('title', 'private', 'tags', 'file', 'duration', 'fragment') extra = 1 -class EpisodeInline (admin.StackedInline): - model = models.Episode - extra = 0 - - class ScheduleInline (admin.TabularInline): - model = models.Schedule - extra = 0 + model = Schedule + 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 # @@ -37,14 +37,13 @@ class MetadataAdmin (admin.ModelAdmin): ( None, { 'fields': [ 'title', 'tags' ] }), - ( 'metadata', { + ( None, { 'fields': [ 'date' ], - 'classes': ['collapse'] }), ] - def save_model(self, request, obj, form, change): + def save_model (self, request, obj, form, change): if not obj.author: obj.author = request.user obj.save() @@ -52,38 +51,31 @@ class MetadataAdmin (admin.ModelAdmin): class PublicationAdmin (MetadataAdmin): + formfield_overrides = { + models.TextField: {'widget': Textarea(attrs={'style':'width:calc(100% - 12px);'})}, + } + fieldsets = copy.deepcopy(MetadataAdmin.fieldsets) - list_display = ('id', 'title', 'date', 'public') - list_filter = ['date', 'public'] + list_display = ('id', 'title', 'date', 'private') + list_filter = ['date', 'private'] search_fields = ['title', 'content'] - def __init__ (self, *args, **kwargs): - self.fieldsets[0][1]['fields'].insert(1, 'subtitle') - self.fieldsets[0][1]['fields'] += [ 'img', 'content' ] - self.fieldsets[1][1]['fields'] += [ 'parent', 'public', 'can_comment', 'meta' ], - return super(PublicationAdmin, self).__init__(*args, **kwargs) + fieldsets[0][1]['fields'].insert(1, 'subtitle') + fieldsets[0][1]['fields'] += [ 'img', 'content' ] + fieldsets[1][1]['fields'] += [ 'parent', 'private', 'can_comment' ] #, 'meta' ], # # ModelAdmin list # -#class TrackAdmin (MetadataAdmin): -# fieldsets = [ -# (None, { 'fields': [ 'title', 'artist', 'version', 'tags'] } ) -# ] - class SoundFileAdmin (MetadataAdmin): fieldsets = [ (None, { 'fields': ['title', 'tags', 'file', 'embed' ] } ), ('metadata', { 'fields': ['duration', 'date', 'podcastable', 'fragment' ] } ) ] - #inlines = [ EpisodeInline ] - #inlines = [ EventInline ] - - class ArticleAdmin (PublicationAdmin): fieldsets = copy.deepcopy(PublicationAdmin.fieldsets) @@ -91,13 +83,11 @@ class ArticleAdmin (PublicationAdmin): fieldsets[1][1]['fields'] += ['static_page'] - class ProgramAdmin (PublicationAdmin): fieldsets = copy.deepcopy(PublicationAdmin.fieldsets) - inlines = [ EpisodeInline, ScheduleInline ] - - fieldsets[1][1]['fields'] += ['email', 'url', 'non_stop'] + inlines = [ ScheduleInline ] + fieldsets[1][1]['fields'] += ['email', 'url'] class EpisodeAdmin (PublicationAdmin): @@ -105,15 +95,16 @@ class EpisodeAdmin (PublicationAdmin): inlines = [ SoundFileInline ] list_filter = ['parent'] + PublicationAdmin.list_filter + # FIXME later: when we have thousands of tracks fieldsets[0][1]['fields'] += ['tracks'] -admin.site.register(models.Track) -admin.site.register(models.SoundFile, SoundFileAdmin) -admin.site.register(models.Schedule) -admin.site.register(models.Article, ArticleAdmin) -admin.site.register(models.Program, ProgramAdmin) -admin.site.register(models.Episode, EpisodeAdmin) -admin.site.register(models.Event) +admin.site.register(Track) +admin.site.register(SoundFile, SoundFileAdmin) +admin.site.register(Schedule) +admin.site.register(Article, ArticleAdmin) +admin.site.register(Program, ProgramAdmin) +admin.site.register(Episode, EpisodeAdmin) +admin.site.register(Diffusion) diff --git a/programs/models.py b/programs/models.py index b6230aa..53a59f5 100755 --- a/programs/models.py +++ b/programs/models.py @@ -12,6 +12,7 @@ from django.utils.html import strip_tags # extensions from taggit.managers import TaggableManager +from sortedm2m.fields import SortedManyToManyField import programs.settings as settings @@ -48,7 +49,7 @@ ugettext_lazy('second and fourth') ugettext_lazy('one on two') -EventType = { +DiffusionType = { 'diffuse': 0x01 # the diffusion is planified or done , 'cancel': 0x03 # the diffusion has been canceled from grid; useful to give # the info to the users @@ -107,10 +108,10 @@ class Metadata (Model): _('date') , default = timezone.datetime.now ) - public = models.BooleanField( - _('public') + private = models.BooleanField( + _('private') , 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 meta = models.TextField( @@ -250,6 +251,14 @@ class Track (Model): 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( 'Episode' , verbose_name = _('episode') @@ -258,7 +267,7 @@ class SoundFile (Metadata): ) file = models.FileField( #FIXME: filefield _('file') - , upload_to = lambda i, f: SoundFile.__upload_path(i,f) + , upload_to = get_upload_path ) duration = models.TimeField( _('duration') @@ -297,14 +306,6 @@ class SoundFile (Metadata): 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): return str(self.id) + ': ' + self.file.name @@ -482,11 +483,6 @@ class Program (Publication): , blank = True , null = True ) - non_stop = models.SmallIntegerField( - _('non-stop priority') - , help_text = _('this program can be used as non-stop') - , default = -1 - ) @property def path (self): @@ -526,10 +522,9 @@ class Episode (Publication): Program , verbose_name = _('parent') ) - tracks = models.ManyToManyField( + tracks = SortedManyToManyField( Track - , verbose_name = _('playlist') - , blank = True + , verbose_name = _('tracks') ) @@ -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 - planified: when it has been generated manually/ponctually or scheduled """ @@ -556,23 +551,29 @@ class Event (Model): Program ) type = models.SmallIntegerField( - _('type') - , choices = [ (y, x) for x,y in EventType.items() ] + verbose_name = _('type') + , 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') + verbose_name = _('stream') , default = 0 - , help_text = 'stream id on which the event happens' + , help_text = 'stream id on which the diffusion happens' ) scheduled = models.BooleanField( - _('automated') + verbose_name = _('automated') , 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: - verbose_name = _('Event') - verbose_name_plural = _('Events') + verbose_name = _('Diffusion') + verbose_name_plural = _('Diffusions') diff --git a/programs/requirements.txt b/programs/requirements.txt index 867b0f3..dd1bb13 100644 --- a/programs/requirements.txt +++ b/programs/requirements.txt @@ -1,4 +1,5 @@ Django>=1.9.0 -taggit +taggit>=0.12.1 +sortedm2m>=1.0.2 diff --git a/programs/settings.py b/programs/settings.py index 9e89c35..01ea004 100755 --- a/programs/settings.py +++ b/programs/settings.py @@ -18,7 +18,7 @@ ensure('AIRCOX_SOUNDFILE_DEFAULT_DIR', ensure('AIRCOX_SOUNDFILE_EXT', ('ogg','flac','wav','mp3','opus')) -# Stream for the scheduled events +# Stream for the scheduled diffusions ensure('AIRCOX_SCHEDULED_STREAM', 0) diff --git a/programs/utils.py b/programs/utils.py index dd969da..1418f35 100644 --- a/programs/utils.py +++ b/programs/utils.py @@ -1,31 +1,31 @@ from django.utils import timezone -from programs.models import Schedule, Event, Episode,\ - EventType +from programs.models import Schedule, Diffusion, Episode,\ + 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 - non existing events, a program attribute to the corresponding program is + Return a list of scheduled diffusions for the month of the given date. For the + non existing diffusions, a program attribute to the corresponding program is set. """ if not date: date = timezone.datetime.today() schedules = Schedule.objects.all() - events = [] + diffusions = [] for schedule in schedules: dates = schedule.dates_of_month() for date in dates: - event = Event.objects \ + diffusion = Diffusion.objects \ .filter(date = date, parent__parent = schedule.parent) - if event.count(): + if diffusion.count(): if not unsaved_only: - events.append(event) + diffusions.append(diffusion) continue # get episode @@ -37,16 +37,16 @@ def scheduled_month_events (date = None, unsaved_only = False): , parent = schedule.parent ) episode = episode[0] if episode.count() else None - # make event - event = Event( parent = episode + # make diffusion + diffusion = Diffusion( parent = episode , program = schedule.parent - , type = EventType['diffuse'] + , type = DiffusionType['diffuse'] , date = date , stream = settings.AIRCOX_SCHEDULED_STREAM , scheduled = True ) - event.program = schedule.program - events.append(event) - return events + diffusion.program = schedule.program + diffusions.append(diffusion) + return diffusions diff --git a/programs/views.py b/programs/views.py index c03618f..60dca72 100755 --- a/programs/views.py +++ b/programs/views.py @@ -7,7 +7,7 @@ import programs.settings -class EventList: +class DiffusionList: type = None next = None prev = None @@ -22,29 +22,29 @@ class EventList: def get_queryset (self): - events = models.Event.objects; + diffusions = models.Diffusion.objects; - if self.next: events = events.filter( date_end__ge = timezone.now() ) - elif self.prev: events = events.filter( date_end__le = timezone.now() ) - else: events = events.all() + if self.next: diffusions = diffusions.filter( date_end__ge = timezone.now() ) + elif self.prev: diffusions = diffusions.filter( date_end__le = timezone.now() ) + else: diffusions = diffusions.all() - events = events.extra(order_by = ['date']) - if self.at: events = events[self.at:] - if self.count: events = events[:self.count] + diffusions = diffusions.extra(order_by = ['date']) + if self.at: diffusions = diffusions[self.at:] + if self.count: diffusions = diffusions[:self.count] - self.events = events + self.diffusions = diffusions def raw_string(): """ - Return a string with events rendered as raw + Return a string with diffusions rendered as raw """ res = [] - for event in events: - r = [ dateformat.format(event.date, "Y/m/d H:i:s") - , str(event.type) - , event.parent.file.path - , event.parent.file.url + for diffusion in diffusions: + r = [ dateformat.format(diffusion.date, "Y/m/d H:i:s") + , str(diffusion.type) + , diffusion.parent.file.path + , diffusion.parent.file.url ] res.push(' '.join(r)) @@ -56,13 +56,13 @@ class EventList: import json res = [] - for event in events: + for diffusion in diffusions: r = { - 'date': dateformat.format(event.date, "Y/m/d H:i:s") - , 'date_end': dateformat.format(event.date_end, "Y/m/d H:i:s") - , 'type': str(event.type) - , 'file_path': event.parent.file.path - , 'file_url': event.parent.file.url + 'date': dateformat.format(diffusion.date, "Y/m/d H:i:s") + , 'date_end': dateformat.format(diffusion.date_end, "Y/m/d H:i:s") + , 'type': str(diffusion.type) + , 'file_path': diffusion.parent.file.path + , 'file_url': diffusion.parent.file.url } res.push(json.dumps(r))